【代碼片斷分享】大量條件判斷,實現條件匹配工具類,代替if...else

簡單用到了jdk8的Stream API,參考幾年前的文章:http://www.javashuo.com/article/p-cacuwnpu-hq.htmljava

舉個例子

一個規則有這麼多字段須要判斷: dom

工具類使用

僞代碼:ide

public boolean match() {

	Matchers matcher = Matchers.builder().isIgnoreNullSourceValue(true).build()
		.eq(sourceValue1, inputValue1)
		.contains(sourceList1, inputValue2);

	if (condition1) {
		matcher.eq(sourceValue2, inputValue3)
				.eq(sourceValue3, inputValue4)
				.contains(sourceList2, inputValue5);

		if (condition2) {
			matcher.eq(sourceValue4, inputValue5)
				.or(
					eq(sourceValue5, inputValue6).and(containMatch(sourceList3, inputValue7)),
					eq(sourceValue6, inputValue8).and(containMatch(sourceList4, inputValue9)),
					eq(sourceValue7, inputValue10)
				);
		} else {
			// 按規則爲準,入參沒傳,但規則有配置,當不匹配
			matcher.unMatch();
		}
	}

	return matcher.stream().allMatch(IMatcher::match);
}

具體實現

Matchers類實現:工具

package com.winning.business.clinical.rules.domain.util;

import com.google.common.collect.Lists;
import com.winning.base.akso.logging.core.WinLogger;
import com.winning.base.akso.logging.core.WinLoggerFactory;
import com.winning.pts.utils.collection.ListUtil;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;

/**
 * @author Fengqik <fqk@winning.com.cn>
 */
@Builder
public class Matchers {

    private static final WinLogger LOGGER = WinLoggerFactory.getCurrentClassLogger();

    /**
     * 是否忽略空的匹配值
     */
    private final boolean isIgnoreNullSourceValue;

    private final List<IMatcher> matchResultList = Lists.newArrayList();

    private final List<List<IMatcher>> matchBundleOrList = Lists.newArrayList();

    private final List<List<IMatcher>> matchBundleAndList = Lists.newArrayList();

    /**
     * 等於匹配<br>
     *
     * @param source source
     * @param target target
     * @return this
     */
    public Matchers eq(Object source, Object target) {
        if (isIgnoreNullSourceValue && isNull(source)) {
            // 忽略source爲空的匹配
        } else {
            this.matchResultList.add(new EqualMatcher(source, target));
        }
        return this;
    }

    /**
     * 必須進行匹配<br>
     *
     * @param source source
     * @param target target
     * @param mustMatch 是否必須判斷
     * @return this
     */
    public Matchers eq(Object source, Object target, Boolean mustMatch) {
        if (mustMatch) {
            if (nonNull(source)) {
                this.matchResultList.add(new EqualMatcher(source, target));
            } else {
                this.matchResultList.add(new EqualMatcher(target, source));
            }
        } else {
            this.eq(source, target);
        }
        return this;
    }

    /**
     * 包含匹配<br>
     *
     * @param sourceList sourceList
     * @param target target
     * @return this
     */
    public Matchers contains(List<?> sourceList, Object target) {
        if (ListUtil.isNotEmpty(sourceList) && nonNull(target)) {
            this.matchResultList.add(new ContainMatcher(sourceList, target));
        }
        return this;
    }

    /**
     * 或匹配<br>
     *
     * @return this
     */
    public Matchers or(MatchBuilder...matchBuilders) {
        if (nonNull(matchBuilders)) {
            for (MatchBuilder matcher : matchBuilders) {
                this.matchBundleOrList.add(matcher.getMatcherList());
            }
        }
        return this;
    }

    /**
     * 設置一個不匹配的校驗結果<br>
     *
     * @return this
     */
    public Matchers unMatch() {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("【UN MATCH】");
        }
        this.matchResultList.add(new NegativeMatcher());
        return this;
    }

    public Stream<IMatcher> stream() {
        if (ListUtil.isNotEmpty(this.matchBundleOrList)) {
            this.matchResultList.add(new BundleOrMatcher(matchBundleOrList));
        }
        if (ListUtil.isNotEmpty(this.matchBundleAndList)) {
            this.matchResultList.add(new BundleAndMatcher(matchBundleAndList));
        }
        return StreamSupport.stream(Spliterators.spliterator(matchResultList, 0), false);
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    static class EqualMatcher implements IMatcher {
        private Object matchSource;
        private Object matchTarget;

        @Override
        public boolean match() {
            boolean flag = false;
            if (nonNull(matchSource)) {
                flag = matchSource.equals(matchTarget);
            } else if (isNull(matchTarget)) {
                flag = true;
            }
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("【EQ MATCH】: {} == {} ? {}", matchSource, matchTarget, flag);
            }
            return flag;
        }
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    static class ContainMatcher implements IMatcher {
        private List<?> matchSourceList;
        private Object matchTarget;

        @Override
        public boolean match() {
            if (ListUtil.isNotEmpty(matchSourceList)) {
                boolean flag = matchSourceList.contains(matchTarget);
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("【CONTAINS MATCH】: {} contains {} ? {}", matchSourceList, matchTarget, flag);
                }
                return flag;
            }
            return false;
        }
    }

    static class NegativeMatcher implements IMatcher {
        @Override
        public boolean match() {
            return false;
        }
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class BundleOrMatcher implements IMatcher {

        private List<List<IMatcher>> bundleList;

        @Override
        public boolean match() {
            if (ListUtil.isNotEmpty(bundleList)) {
                return bundleList.stream().anyMatch(bundle -> {
                    if (ListUtil.isNotEmpty(bundle)) {
                        return bundle.stream().allMatch(IMatcher::match);
                    }
                    return false;
                });
            }
            return false;
        }
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class BundleAndMatcher implements IMatcher {

        private List<List<IMatcher>> bundleList;

        @Override
        public boolean match() {
            if (ListUtil.isNotEmpty(bundleList)) {
                return bundleList.stream().allMatch(bundle -> {
                    if (ListUtil.isNotEmpty(bundle)) {
                        return bundle.stream().allMatch(IMatcher::match);
                    }
                    return false;
                });
            }
            return false;
        }
    }

    public interface IMatcher {

        /**
         * 匹配
         *
         * @return true or false
         */
        boolean match();
    }

    @Data
    public static class MatchBuilder {

        /**
         *
         */
        private final List<IMatcher> matcherList = Lists.newArrayList();

        public static MatchBuilder eq(Object source, Object target) {
            MatchBuilder matchBuilder = new MatchBuilder();
            matchBuilder.getMatcherList().add(new EqualMatcher(source, target));
            return matchBuilder;
        }

        public static IMatcher eqMatch(Object source, Object target) {
            return new EqualMatcher(source, target);
        }

        public static IMatcher containMatch(List<?> sourceList, Object target) {
            return new ContainMatcher(sourceList, target);
        }

        public static MatchBuilder contain(List<?> sourceList, Object target) {
            MatchBuilder matchBuilder = new MatchBuilder();
            matchBuilder.getMatcherList().add(new ContainMatcher(sourceList, target));
            return matchBuilder;
        }

        public MatchBuilder and(IMatcher iMatcher) {
            this.matcherList.add(iMatcher);
            return this;
        }

    }

}

拋磚引玉ui

相關文章
相關標籤/搜索