Modèles de conception - Modèles composites (arbres de décision)

1. Juste comme première vue

        Le mode combinaison peut être la première chose à laquelle vous pensez est de combiner les deux modules. En fait, cela semble être le cas, mais ce n'est pas le cas. Pas beaucoup de bêtises. Pour apprendre une nouvelle chose, vous devez d'abord comprendre son concept Les anciennes règles d'abord Sur le concept (extrait de l'encyclopédie Baidu):

Mode composite_Encyclopédie Baidu Le mode composite, qui combine des objets dans une structure arborescente pour représenter la hiérarchie "partie-tout". https://baike.baidu.com/item/%E7%BB%84%E5%90%88%E6%A8%A1%E5%BC%8F/1441281?fromModule=lemma_inlink

       Après avoir lu le concept et y avoir réfléchi, il est complètement différent de ce que je pensais. Récemment, j'ai parlé de ce modèle de conception en mettant l'accent sur l'apprentissage des modèles de conception Java. Il est facile à comprendre (pas d'obscurité officielle) et à retirer Partagez-le avec tout le monde ; la suggestion à tout le monde est que vous pouvez vous sentir à moitié compris après l'avoir relu, mais vous le trouverez clair lorsque vous l'écrivez à nouveau.

2. Entrée

        Je crois que tout le monde a joué avec des blocs de construction ou des jouets Lego, et chaque partie a ses propres responsabilités et fonctions. Par exemple, une voiture ne peut pas marcher uniquement avec des roues, elle doit être composée d'un moteur, d'un châssis, d'une carrosserie, d'équipements électriques et d'autres composants.

        L'utilisation de la combinaison de fonctions ABCD pour fournir des services externes comme celui-ci est similaire au mode de combinaison. Quelles sont les caractéristiques de l'implémentation du code ? Alors, quels sont les avantages de l'utiliser pour le projet ? Quels sont les avantages de le rejoindre pour l'équipe ? Trois questions de l'âme, peut-être avez-vous des questions similaires qui circulent dans votre esprit, comme celle-ci.

Juste une blague pour que tout le monde détende sa pensée tendue, passons aux choses sérieuses.

3. Décoller les cocons

3.1 Fonctionnalités de mise en œuvre

Quoi? Vous êtes encore un peu confus après avoir lu ceci. En effet, c'est un peu officiel, si ce n'est pas facile à comprendre, vous pouvez regarder cette photo :

C'est probablement facile à expliquer. En supposant que le produit a une exigence commerciale, j'ai d'abord trouvé le responsable. Le responsable a dit que je sais qui peut le faire. J'ai trouvé le chef de l'équipe A. Après avoir compris les besoins, le chef de l'équipe A assigné des tâches spécifiques aux ingénieurs correspondants. ; Je crois qu'après avoir lu ce que j'ai dit, vous avez probablement un concept un peu flou dans votre esprit, et vous avez déjà hâte de l'essayer ; ne vous inquiétez pas, continuons à lire .

3.2 Avantages de rejoindre le projet / bénéfices pour l'équipe

        Plus tôt, nous avons appris que ce modèle de conception est en fait une structure arborescente. La recherche récursive des fonctions correspondantes peut faciliter l'extension et la maintenance du code, et réduire les coûts de maintenance de l'équipe. Le plus important est d'éviter les plaintes des partenaires successeurs. . À ce moment-là, quelqu'un l'a réfuté. Je ne pense pas. N'est-ce pas simplement parce que j'ai ajouté un if else ? Doit-il être aussi imprévisible ? Il est normal d'avoir des doutes, j'avais aussi des doutes similaires lorsque je l'ai lu pour la première fois, mais je pense que vous n'aurez pas de doutes similaires après avoir lu la dernière partie.

Quatrièmement, tirez des conclusions à partir d'une instance

        Nous avons mentionné précédemment que ce design pattern n'est en fait pas bénéfique, c'est une question de if else pour la réalisation des fonctions, donnons un exemple pour que chacun réfléchisse à la raison pour laquelle cet exemple est utilisé.

4.1 Contre-exemple     

Voici un exemple de scénario commercial réel de produit et de R&D :

date besoin Programmeur (monologue intérieur)
Lundi matin) Frère, l'entreprise a déclaré qu'il y avait un besoin urgent, et nous devons ajouter un jugement ici pour émettre différentes incitations selon différents canaux. Bien. (Ce n'est pas difficile, ajoutez simplement un jugement ici et vous pourrez aller en ligne)

Mardi

(après-midi)

Frère, l'effet en ligne est très bon. L'entreprise a déclaré qu'elle devrait être subdivisée en différents types d'entreprise pour motiver l'équipe. Ce n'est pas difficile non plus. (Ajouter un type pour juger la ligne)

Mercredi

(nuit)

Bonjour, tu dors ? L'entreprise a déclaré que la division réalisée cette fois était très bonne et qu'elle devait être subdivisée en fonction du volume des ventes de l'équipe sous la subdivision. D'accord, ajoutez. (déjà réalisé si le reste est un peu trop)

Jeudi

(tôt le matin)

Wow, vous êtes géniaux, vous êtes allés en ligne très rapidement, il y a une petite exigence, vous devez ajuster les incitations en fonction des ventes individuelles dans l'équipe. Eh bien, plus. (beaucoup de if else à modifier)

Vendredi

(minuit)

Hé, c'est cassé. Pourquoi la récompense est-elle mal envoyée ? Le côté commercial a commencé à se plaindre. Veuillez vérifier quel est le problème. (laisse des larmes de regret)

Code:

public class EngineController {

    private Logger logger = LoggerFactory.getLogger(EngineController.class);

    public String process(final String channelId, final String userId, final BigDecimal teamSalesVolume,final BigDecimal salesVolume) {

        logger.info("ifelse实现方式判断用户结果。channelId:{} userId:{} teamSalesVolume:{} salesVolume:{}", channelId, userId, teamSalesVolume,salesVolume);

        if ("0001".equals(channelId)) {
            if (new BigDecimal("1000").compareTo(teamSalesVolume)>0||new BigDecimal("1000").compareTo(salesVolume)>0) {
                return "奖励A";
            }

            if (new BigDecimal("1000").compareTo(teamSalesVolume)<=0||new BigDecimal("1000").compareTo(salesVolume)<=0) {
                return "奖励B";
            }
        }

        if ("0002".equals(channelId)) {
            if (new BigDecimal("1000").compareTo(teamSalesVolume)>0||new BigDecimal("1000").compareTo(salesVolume)>0) {
                return "奖励C";
            }

            if (new BigDecimal("1000").compareTo(teamSalesVolume)<=0||new BigDecimal("1000").compareTo(salesVolume)<=0) {
                return "奖励D";
            }
        }

        return null;

    }


}

        À en juger par les résultats ci-dessus, c'est sans aucun doute le moyen le plus rapide de réaliser la logique correspondante, mais s'il y a trop de if else dans le suivi, cela deviendra le mauvais code final, ce qui aura un impact variable sur la maintenance ultérieure. et itération.

4.2 Exemple positif

Répertoire du projet

Commençons par expliquer les fonctions et fonctions des modules correspondants selon le niveau 

4.2.1  Interface de filtre d'origine LogicFilter

LogicFilter : l'interface de filtrage d'origine, qui définit la méthode de comportement d'origine, la méthode de décision logique et la méthode d'obtention de la valeur de décision. Chaque nœud qui fournit des capacités de prise de décision doit implémenter cette interface.

package cn.test.design.domain.service.logic;

import java.util.List;
import java.util.Map;

import cn.test.design.domain.model.vo.TreeNodeLink;

/**
 * 原始决策过滤器
 */
public interface LogicFilter {

    /**
     * 逻辑决策器
     *
     * @param matterValue          决策值
     * @param treeNodeLineInfoList 决策节点
     * @return 下一个节点Id
     */
    Long filter(String matterValue, List<TreeNodeLink> treeNodeLineInfoList);

    /**
     * 获取决策值
     *
     * @param decisionMatter 决策物料
     * @return 决策值
     */
    String matterValue(Long treeId, String userId, Map<String, String> decisionMatter);

}

4.2.2  Implémentation de base de l'abstraction BaseLogic

BaseLogic : L'abstraction implémente essentiellementla logique de décision de base dans LogicFilter selon la logique de jugement supérieur ou égal à, inférieur à, etc. selon différents types. En même temps, elle définit une méthode abstraite afin que toutes les classes qui implémentent il doit implémenter la méthode d'obtention d'une valeur de décision Cette valeur de décision est utilisée pour la comparaison logique .

package cn.test.design.domain.service.logic;


import java.util.List;
import java.util.Map;

import cn.test.design.domain.model.vo.TreeNodeLink;

/**
 * 过滤器抽象基本实现实现,实现基本基本决策逻辑
 */
public abstract class BaseLogic implements LogicFilter {
	
	/**
	 * 实现基本基本决策逻辑
	 */
    @Override
    public Long filter(String matterValue, List<TreeNodeLink> treeNodeLinkList) {
        for (TreeNodeLink nodeLine : treeNodeLinkList) {
            if (decisionLogic(matterValue, nodeLine)) return nodeLine.getNodeIdTo();
        }
        return 0L;
    }
    
    /**
     * 让子类必须实现获取决策值的方法用于对比获取最终的结果
     */
    @Override
    public abstract String matterValue(Long treeId, String userId, Map<String, String> decisionMatter);

    private boolean decisionLogic(String matterValue, TreeNodeLink nodeLink) {
        switch (nodeLink.getRuleLimitType()) {
            case 1:
                return matterValue.equals(nodeLink.getRuleLimitValue());
            case 2:
                return Double.parseDouble(matterValue) > Double.parseDouble(nodeLink.getRuleLimitValue());
            case 3:
                return Double.parseDouble(matterValue) < Double.parseDouble(nodeLink.getRuleLimitValue());
            case 4:
                return Double.parseDouble(matterValue) <= Double.parseDouble(nodeLink.getRuleLimitValue());
            case 5:
                return Double.parseDouble(matterValue) >= Double.parseDouble(nodeLink.getRuleLimitValue());
            default:
                return false;
        }
    }

}

4.2.3 Implémentation du nœud racine de l'arborescence (ChannelGenderFilter, UserSalesVolumeFilter)

Ici, notre scénario commercial actuel n'utilise que des canaux et des ventes, il n'y en a donc que deux définis à l'heure actuelle, et d'autres peuvent être définis si les besoins réels ; bien sûr, à l'heure actuelle, la valeur matérielle est obtenue directement. Dans le développement réel, il doit être basé sur le fichier de configuration ou depuis l'interface rpc ou depuis le Obtenir les informations requises de la base de données.

ChannelGenderFilter : nœud de canal

package cn.test.design.domain.service.logic.impl;

import java.util.Map;

import cn.test.design.domain.service.logic.BaseLogic;

/**
 * 
 * 渠道基本过滤器
 *
 */
public class ChannelGenderFilter extends BaseLogic {

	@Override
	public String matterValue(Long treeId, String userId, Map<String, String> decisionMatter) {
		// 目前是直接获取物料值,实际开发中肯定是根据配置文件或从rpc接口或从数据库中获取对应需要的信息。
		return decisionMatter.get("channel");
	}

}

UserSalesVolumeFilter : ventes des utilisateurs

package cn.test.design.domain.service.logic.impl;

import java.util.Map;

import cn.test.design.domain.service.logic.BaseLogic;
/**
 * 用户销售额过滤器
 *
 */
public class UserSalesVolumeFilter extends BaseLogic {

    @Override
    public String matterValue(Long treeId, String userId, Map<String, String> decisionMatter) {
    	// 目前是直接获取物料值,实际开发中肯定是根据配置文件或从rpc接口或从数据库中获取对应需要的信息.
    	return decisionMatter.get("userSalesVolume");
    }

}

4.2.4 Moteur de décision IEngine

        L'interface du moteur de décision fournie à l'appelant. Après avoir défini la méthode correspondante, s'il existe une nouvelle logique de décision, la méthode correspondante peut être implémentée.

package cn.test.design.domain.service.engine;

import java.util.Map;

import cn.test.design.domain.model.aggregates.TreeRich;
import cn.test.design.domain.model.vo.EngineResult;

/**
 * 决策引擎接口
 *
 */
public interface IEngine {
	
    EngineResult process(final Long treeId, final String userId, TreeRich treeRich, final Map<String, String> decisionMatter);

}

4.2.5 Configuration du nœud de décision EngineConfig

        La configuration de prise de décision ici est actuellement fixée avec deux implémentations de nœud racine d'arborescence ( ChannelGenderFilter , UserSalesVolumeFilter ).Le scénario réel consiste à configurer l'implémentation requise dans la table, qui peut être configurée de manière pratique dans l'arrière-plan de l'opération.

package cn.test.design.domain.service.engine;


import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import cn.test.design.domain.service.logic.LogicFilter;
import cn.test.design.domain.service.logic.impl.ChannelGenderFilter;
import cn.test.design.domain.service.logic.impl.UserSalesVolumeFilter;

/**
 * 
 * 决策节点配置,此处可以配置至数据库中方便后续界面操作维护
 *
 */
public class EngineConfig {

    static Map<String, LogicFilter> logicFilterMap;

    static {
        logicFilterMap = new ConcurrentHashMap<>();
        logicFilterMap.put("channel", new ChannelGenderFilter());
        logicFilterMap.put("userSalesVolume", new UserSalesVolumeFilter());
    }

    public Map<String, LogicFilter> getLogicFilterMap() {
        return logicFilterMap;
    }

    @SuppressWarnings("static-access")
	public void setLogicFilterMap(Map<String, LogicFilter> logicFilterMap) {
        this.logicFilterMap = logicFilterMap;
    }

}

4.2.6 Moteur de décision de base EngineBase

        Voici le flux principal de traitement de l'arbre de décision, un peu comme la recherche du fruit des feuilles. Dans le même temps, le moteur de décision de base IEngine est implémenté

Mais il ne fournit que l'abstraction et ne l'implémente pas, et il est implémenté par le moteur de classe d'implémentation de prise de décision finale.

package cn.test.design.domain.service.engine;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.test.design.domain.model.aggregates.TreeRich;
import cn.test.design.domain.model.vo.EngineResult;
import cn.test.design.domain.model.vo.TreeNode;
import cn.test.design.domain.model.vo.TreeRoot;
import cn.test.design.domain.service.logic.LogicFilter;

/**
 * 决策树引擎
 */
public abstract class EngineBase extends EngineConfig implements IEngine {

    private Logger logger = LoggerFactory.getLogger(EngineBase.class);

    @Override
    public abstract EngineResult process(Long treeId, String userId, TreeRich treeRich, Map<String, String> decisionMatter);

    protected TreeNode engineDecisionMaker(TreeRich treeRich, Long treeId, String userId, Map<String, String> decisionMatter) {
        TreeRoot treeRoot = treeRich.getTreeRoot();
        Map<Long, TreeNode> treeNodeMap = treeRich.getTreeNodeMap();
        // 规则树根ID
        Long rootNodeId = treeRoot.getTreeRootNodeId();
        TreeNode treeNodeInfo = treeNodeMap.get(rootNodeId);
        //循环获取对应的处理节点直到获取到对应的结果
        //节点类型[NodeType];1子叶、2果实 我们只需要使用果实
        while (treeNodeInfo.getNodeType().equals(1)) {
            //对应处理规则key用于获取对应实现LogicFilter 的处理节点主要用来获取物料中用于对比的相关值
        	String ruleKey = treeNodeInfo.getRuleKey();
        	//实际的处理节点
            LogicFilter logicFilter = logicFilterMap.get(ruleKey);
            String matterValue = logicFilter.matterValue(treeId, userId, decisionMatter);
            //基础决策抽象中的能力,使用物料值判断使用那个决策节点(获取的是下一个节点)
            Long nextNode = logicFilter.filter(matterValue, treeNodeInfo.getTreeNodeLinkList());
            //赋值对应的处理节点,直到找到期望的处理节点(我们这里是最终的果实节点)
            treeNodeInfo = treeNodeMap.get(nextNode);
            logger.info("决策树引擎=>{} userId:{} treeId:{} treeNode:{} ruleKey:{} matterValue:{}", treeRoot.getTreeName(), userId, treeId, treeNodeInfo.getTreeNodeId(), ruleKey, matterValue);
        }
        return treeNodeInfo;
    }

}

4.2.7 Implémentation du moteur de décision de base TreeEngineHandle

        Il est fondamentalement relativement simple d'utiliser la valeur correspondante passée par l'utilisateur directement à la méthode correspondante pour obtenir le résultat correspondant

package cn.test.design.domain.service.engine.impl;

import java.util.Map;

import cn.test.design.domain.model.aggregates.TreeRich;
import cn.test.design.domain.model.vo.EngineResult;
import cn.test.design.domain.model.vo.TreeNode;
import cn.test.design.domain.service.engine.EngineBase;
/**
 * 基础决策引擎实现
 *
 */
public class TreeEngineHandle extends EngineBase {

    @Override
    public EngineResult process(Long treeId, String userId, TreeRich treeRich, Map<String, String> decisionMatter) {
        // 决策流程
        TreeNode treeNode = engineDecisionMaker(treeRich, treeId, userId, decisionMatter);
        // 决策结果
        return new EngineResult(userId, treeId, treeNode.getTreeNodeId(), treeNode.getNodeValue());
    }

}

4.2.8 Tests unitaires

        La configuration initiale ici est actuellement configurée manuellement et le code réel peut utiliser la configuration de la base de données pour configurer dynamiquement les informations de nœud requises.

package cn.test.design.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;

import cn.test.design.domain.model.aggregates.TreeRich;
import cn.test.design.domain.model.vo.EngineResult;
import cn.test.design.domain.model.vo.TreeNode;
import cn.test.design.domain.model.vo.TreeNodeLink;
import cn.test.design.domain.model.vo.TreeRoot;
import cn.test.design.domain.service.engine.IEngine;
import cn.test.design.domain.service.engine.impl.TreeEngineHandle;

public class ApiTest {

    private Logger logger = LoggerFactory.getLogger(ApiTest.class);

    private TreeRich treeRich;

    @Before
    public void init() {

        // 节点:1
        TreeNode treeNode_01 = new TreeNode();
        treeNode_01.setTreeId(10001L);
        treeNode_01.setTreeNodeId(1L);
        treeNode_01.setNodeType(1);
        treeNode_01.setNodeValue(null);
        treeNode_01.setRuleKey("channel");
        treeNode_01.setRuleDesc("渠道");

        // 链接:1->11
        TreeNodeLink treeNodeLink_11 = new TreeNodeLink();
        treeNodeLink_11.setNodeIdFrom(1L);
        treeNodeLink_11.setNodeIdTo(11L);
        treeNodeLink_11.setRuleLimitType(1);
        treeNodeLink_11.setRuleLimitValue("0001");

        // 链接:1->12
        TreeNodeLink treeNodeLink_12 = new TreeNodeLink();
        treeNodeLink_12.setNodeIdTo(1L);
        treeNodeLink_12.setNodeIdTo(12L);
        treeNodeLink_12.setRuleLimitType(1);
        treeNodeLink_12.setRuleLimitValue("0002");

        List<TreeNodeLink> treeNodeLinkList_1 = new ArrayList<>();
        treeNodeLinkList_1.add(treeNodeLink_11);
        treeNodeLinkList_1.add(treeNodeLink_12);

        treeNode_01.setTreeNodeLinkList(treeNodeLinkList_1);

        // 节点:11
        TreeNode treeNode_11 = new TreeNode();
        treeNode_11.setTreeId(10001L);
        treeNode_11.setTreeNodeId(11L);
        treeNode_11.setNodeType(1);
        treeNode_11.setNodeValue(null);
        treeNode_11.setRuleKey("userSalesVolume");
        treeNode_11.setRuleDesc("销售额A");

        // 链接:11->111
        TreeNodeLink treeNodeLink_111 = new TreeNodeLink();
        treeNodeLink_111.setNodeIdFrom(11L);
        treeNodeLink_111.setNodeIdTo(111L);
        treeNodeLink_111.setRuleLimitType(3);
        treeNodeLink_111.setRuleLimitValue("25");

        // 链接:11->112
        TreeNodeLink treeNodeLink_112 = new TreeNodeLink();
        treeNodeLink_112.setNodeIdFrom(11L);
        treeNodeLink_112.setNodeIdTo(112L);
        treeNodeLink_112.setRuleLimitType(5);
        treeNodeLink_112.setRuleLimitValue("25");

        List<TreeNodeLink> treeNodeLinkList_11 = new ArrayList<>();
        treeNodeLinkList_11.add(treeNodeLink_111);
        treeNodeLinkList_11.add(treeNodeLink_112);

        treeNode_11.setTreeNodeLinkList(treeNodeLinkList_11);

        // 节点:12
        TreeNode treeNode_12 = new TreeNode();
        treeNode_12.setTreeId(10001L);
        treeNode_12.setTreeNodeId(12L);
        treeNode_12.setNodeType(1);
        treeNode_12.setNodeValue(null);
        treeNode_12.setRuleKey("userSalesVolume");
        treeNode_12.setRuleDesc("销售额B");

        // 链接:12->121
        TreeNodeLink treeNodeLink_121 = new TreeNodeLink();
        treeNodeLink_121.setNodeIdFrom(12L);
        treeNodeLink_121.setNodeIdTo(121L);
        treeNodeLink_121.setRuleLimitType(3);
        treeNodeLink_121.setRuleLimitValue("25");

        // 链接:12->122
        TreeNodeLink treeNodeLink_122 = new TreeNodeLink();
        treeNodeLink_122.setNodeIdFrom(12L);
        treeNodeLink_122.setNodeIdTo(122L);
        treeNodeLink_122.setRuleLimitType(5);
        treeNodeLink_122.setRuleLimitValue("25");

        List<TreeNodeLink> treeNodeLinkList_12 = new ArrayList<>();
        treeNodeLinkList_12.add(treeNodeLink_121);
        treeNodeLinkList_12.add(treeNodeLink_122);

        treeNode_12.setTreeNodeLinkList(treeNodeLinkList_12);

        // 节点:111
        TreeNode treeNode_111 = new TreeNode();
        treeNode_111.setTreeId(10001L);
        treeNode_111.setTreeNodeId(111L);
        treeNode_111.setNodeType(2);
        treeNode_111.setNodeValue("果实A");

        // 节点:112
        TreeNode treeNode_112 = new TreeNode();
        treeNode_112.setTreeId(10001L);
        treeNode_112.setTreeNodeId(112L);
        treeNode_112.setNodeType(2);
        treeNode_112.setNodeValue("果实B");

        // 节点:121
        TreeNode treeNode_121 = new TreeNode();
        treeNode_121.setTreeId(10001L);
        treeNode_121.setTreeNodeId(121L);
        treeNode_121.setNodeType(2);
        treeNode_121.setNodeValue("果实C");

        // 节点:122
        TreeNode treeNode_122 = new TreeNode();
        treeNode_122.setTreeId(10001L);
        treeNode_122.setTreeNodeId(122L);
        treeNode_122.setNodeType(2);
        treeNode_122.setNodeValue("果实D");

        // 树根
        TreeRoot treeRoot = new TreeRoot();
        treeRoot.setTreeId(10001L);
        treeRoot.setTreeRootNodeId(1L);
        treeRoot.setTreeName("规则决策树");

        Map<Long, TreeNode> treeNodeMap = new HashMap<>();
        treeNodeMap.put(1L, treeNode_01);
        treeNodeMap.put(11L, treeNode_11);
        treeNodeMap.put(12L, treeNode_12);
        treeNodeMap.put(111L, treeNode_111);
        treeNodeMap.put(112L, treeNode_112);
        treeNodeMap.put(121L, treeNode_121);
        treeNodeMap.put(122L, treeNode_122);

        treeRich = new TreeRich(treeRoot, treeNodeMap);

    }

    @Test
    public void test_tree() {
        logger.info("决策树组合结构信息:\r\n" + JSON.toJSONString(treeRich));

        IEngine treeEngineHandle = new TreeEngineHandle();

        /**
         * 测试数据
         * 果实A:gender=man、age=22
         * 果实B:gender=man、age=29
         * 果实C:gender=woman、age=22
         * 果实D:gender=woman、age=29
         */
        Map<String, String> decisionMatter = new HashMap<>();
        decisionMatter.put("channel", "0001");
        decisionMatter.put("userSalesVolume", "29");

        EngineResult result = treeEngineHandle.process(10001L, "Oli09pLkdjh", treeRich, decisionMatter);
        logger.info("测试结果:{}", JSON.toJSONString(result));

    }

    @Test
    public void t() {
        
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01000011", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01101111", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01100100", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01101001", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01101110", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01100111", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01001000", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01100101", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01101100", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01110000", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01110011", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01001100", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01101001", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01100110", 2)).trim()));
        System.out.println(hexStringToString(String.format("%21X", Long.parseLong("01100101", 2)).trim()));
    }

    public static String hexStringToString(String s) {
        if (s == null || s.equals("")) {
            return null;
        }
        s = s.replace(" ", "");
        byte[] baKeyword = new byte[s.length() / 2];
        for (int i = 0; i < baKeyword.length; i++) {
            try {
                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        try {
            s = new String(baKeyword, "UTF-8");
            new String();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return s;
    }
}

4.2.9 Classes de nœuds de base associées

        Notez ici les classes de base pertinentes

cn.test.design.domain.model.agrégats ArbreRiche

agrégation d'arborescence de règles

Organiser chaque nœud de l'arbre (feuilles, fruits)

cn.test.design.domain.model.vo MoteurRésultat résultat de la décision
cn.test.design.domain.model.vo TreeNode Informations sur le nœud de l'arborescence des règles
cn.test.design.domain.model.vo TreeNodeLink Les informations sur la ligne de l'arbre de règles relient les nœuds feuilles et les nœuds fruits
cn.test.design.domain.model.vo Racine d'arbre informations racine

Agrégation d'arborescence de règles TreeRich

package cn.test.design.domain.model.aggregates;

import java.util.Map;

import cn.test.design.domain.model.vo.TreeNode;
import cn.test.design.domain.model.vo.TreeRoot;

/**
 * 规则树聚合
 */
public class TreeRich {
	// 树根信息
	private TreeRoot treeRoot;
	// 树节点ID -> 子节点
	private Map<Long, TreeNode> treeNodeMap;

	public TreeRich(TreeRoot treeRoot, Map<Long, TreeNode> treeNodeMap) {
		this.treeRoot = treeRoot;
		this.treeNodeMap = treeNodeMap;
	}

	public TreeRoot getTreeRoot() {
		return treeRoot;
	}

	public void setTreeRoot(TreeRoot treeRoot) {
		this.treeRoot = treeRoot;
	}

	public Map<Long, TreeNode> getTreeNodeMap() {
		return treeNodeMap;
	}

	public void setTreeNodeMap(Map<Long, TreeNode> treeNodeMap) {
		this.treeNodeMap = treeNodeMap;
	}
}

Résultat de la décision EngineResult

package cn.test.design.domain.model.vo;

/**
 * 决策结果
 */
public class EngineResult {

	// 执行结果
	private boolean isSuccess;
	// 用户ID
	private String userId;
	// 规则树ID
	private Long treeId;
	// 果实节点ID
	private Long nodeId;
	// 果实节点值
	private String nodeValue;

	public EngineResult() {
	}

	public EngineResult(boolean isSuccess) {
		this.isSuccess = isSuccess;
	}

	public EngineResult(String userId, Long treeId, Long nodeId, String nodeValue) {
		this.isSuccess = true;
		this.userId = userId;
		this.treeId = treeId;
		this.nodeId = nodeId;
		this.nodeValue = nodeValue;
	}

	public boolean isSuccess() {
		return isSuccess;
	}

	public void setSuccess(boolean success) {
		isSuccess = success;
	}

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public Long getTreeId() {
		return treeId;
	}

	public void setTreeId(Long treeId) {
		this.treeId = treeId;
	}

	public Long getNodeId() {
		return nodeId;
	}

	public void setNodeId(Long nodeId) {
		this.nodeId = nodeId;
	}

	public String getNodeValue() {
		return nodeValue;
	}

	public void setNodeValue(String nodeValue) {
		this.nodeValue = nodeValue;
	}
}

Informations sur le nœud de l'arborescence des règles TreeNode

package cn.test.design.domain.model.vo;

import java.util.List;

/**
 * 规则树节点信息
 */
public class TreeNode {

	// 规则树ID
	private Long treeId;
	// 规则树节点ID
	private Long treeNodeId;
	// 节点类型;1叶子、2 果实
	private Integer nodeType;
	// 节点值[nodeType=2];果实值
	private String nodeValue;
	// 规则Key
	private String ruleKey;
	// 规则描述
	private String ruleDesc;
	// 节点链路
	private List<TreeNodeLink> treeNodeLinkList; 

	public Long getTreeId() {
		return treeId;
	}

	public void setTreeId(Long treeId) {
		this.treeId = treeId;
	}

	public Long getTreeNodeId() {
		return treeNodeId;
	}

	public void setTreeNodeId(Long treeNodeId) {
		this.treeNodeId = treeNodeId;
	}

	public Integer getNodeType() {
		return nodeType;
	}

	public void setNodeType(Integer nodeType) {
		this.nodeType = nodeType;
	}

	public String getNodeValue() {
		return nodeValue;
	}

	public void setNodeValue(String nodeValue) {
		this.nodeValue = nodeValue;
	}

	public String getRuleKey() {
		return ruleKey;
	}

	public void setRuleKey(String ruleKey) {
		this.ruleKey = ruleKey;
	}

	public String getRuleDesc() {
		return ruleDesc;
	}

	public void setRuleDesc(String ruleDesc) {
		this.ruleDesc = ruleDesc;
	}

	public List<TreeNodeLink> getTreeNodeLinkList() {
		return treeNodeLinkList;
	}

	public void setTreeNodeLinkList(List<TreeNodeLink> treeNodeLinkList) {
		this.treeNodeLinkList = treeNodeLinkList;
	}

}

Les informations de la ligne de l'arbre de règles relient les nœuds feuilles et les nœuds fruits TreeNodeLink

package cn.test.design.domain.model.vo;

/**
 * 规则树线信息 链接叶子节点和果实节点
 */
public class TreeNodeLink {

	// 节点From
	private Long nodeIdFrom;
	// 节点To
	private Long nodeIdTo;
	// 限定类型;1:=;2:>;3:<;4:>=;5<=;6:enum[枚举范围]
	private Integer ruleLimitType;
	// 限定值
	private String ruleLimitValue;

	public Long getNodeIdFrom() {
		return nodeIdFrom;
	}

	public void setNodeIdFrom(Long nodeIdFrom) {
		this.nodeIdFrom = nodeIdFrom;
	}

	public Long getNodeIdTo() {
		return nodeIdTo;
	}

	public void setNodeIdTo(Long nodeIdTo) {
		this.nodeIdTo = nodeIdTo;
	}

	public Integer getRuleLimitType() {
		return ruleLimitType;
	}

	public void setRuleLimitType(Integer ruleLimitType) {
		this.ruleLimitType = ruleLimitType;
	}

	public String getRuleLimitValue() {
		return ruleLimitValue;
	}

	public void setRuleLimitValue(String ruleLimitValue) {
		this.ruleLimitValue = ruleLimitValue;
	}
}

Informations sur la racine de l'arborescence TreeRoot

package cn.test.design.domain.model.vo;

/**
 * 树根信息
 */
public class TreeRoot {

	// 规则树ID
	private Long treeId;
	// 规则树根ID
	private Long treeRootNodeId;
	// 规则树名称
	private String treeName;

	public Long getTreeId() {
		return treeId;
	}

	public void setTreeId(Long treeId) {
		this.treeId = treeId;
	}

	public Long getTreeRootNodeId() {
		return treeRootNodeId;
	}

	public void setTreeRootNodeId(Long treeRootNodeId) {
		this.treeRootNodeId = treeRootNodeId;
	}

	public String getTreeName() {
		return treeName;
	}

	public void setTreeName(String treeName) {
		this.treeName = treeName;
	}
}

5. Mettez les voiles

        Au final, avez-vous trouvé que ce mode est comme un ordinateur hôte, et différentes interfaces peuvent être combinées et branchées, et différentes configurations peuvent être configurées à tout moment.Ce mode garantit le principe d'ouverture et de fermeture.Tant que le la structure correspondante est définie au stade précoce, chaque nouveau Pour augmenter la demande, il vous suffit d'ajouter des nœuds correspondants, ou les deux peuvent être utilisés comme mode d'arrière-plan de l'opération, et les règles de routage correspondantes peuvent être configurées dynamiquement par l'opération pour faciliter les opérations ultérieures. entretien.

Références dans cet article :

"Réapprendre les modèles de conception Java" - Commissaire politique de Fu.

  Encyclopédie Baidu.

Je suppose que tu aimes

Origine blog.csdn.net/m0_37506254/article/details/128051240
conseillé
Classement