基于责任树构建demo

原文链接:https://mp.weixin.qq.com/s/Wib0Ly45te00HMUnIG-tbg

调用使用对应的责任树

package com.li.myspringbootmybatis.controller;

import com.alibaba.fastjson.JSONObject;
import com.li.myspringbootmybatis.strategy.a.A;
import com.li.myspringbootmybatis.strategy.root.Root;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;

/**
 * @author lym
 */
@Controller
public class TestException {
    @Resource
    private Root root;
    
    @GetMapping("/testStrategy")
    @ResponseBody
    public void test(){
        //root节点中传入参数获取A的处理策略
        root.applyStrategy("A");

    }
}

1. 创建AbstractStrategyRouter(将文章中的抽象类复制到文本编辑中即可)

package com.li.myspringbootmybatis.strategy;

import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Objects;

/**
 * 通用的“策略树“框架,通过树形结构实现分发与委托,每层通过指定的参数进行向下分发委托,直到达到最终的执行者。
 * 该框架包含两个类:{@code StrategyHandler} 和 {@code AbstractStrategyRouter}
 * 其中:通过实现 {@code AbstractStrategyRouter} 抽象类完成对策略的分发,
 * 实现 {@code StrategyHandler} 接口来对策略进行实现。
 * 像是第二层 A、B 这样的节点,既是 Root 节点的策略实现者也是策略A1、A2、B1、B2 的分发者,这样的节点只需要
 * 同时继承 {@code StrategyHandler} 和实现 {@code AbstractStrategyRouter} 接口就可以了。
 *
 * <pre>
 *           +---------+
 *           |  Root   |   ----------- 第 1 层策略入口
 *           +---------+
 *            /       \  ------------- 根据入参 P1 进行策略分发
 *           /         \
 *     +------+      +------+
 *     |  A   |      |  B   |  ------- 第 2 层不同策略的实现
 *     +------+      +------+
 *       /  \          /  \  --------- 根据入参 P2 进行策略分发
 *      /    \        /    \
 *   +---+  +---+  +---+  +---+
 *   |A1 |  |A2 |  |B1 |  |B2 |  ----- 第 3 层不同策略的实现
 *   +---+  +---+  +---+  +---+
 * </pre>
 *
 * @author
 * @date
 * @see StrategyHandler
 */
@Component
public abstract class AbstractStrategyRouter<T, R> {

    /**
     * 策略映射器,根据指定的入参路由到对应的策略处理者。
     *
     * @param <T> 策略的入参类型
     * @param <R> 策略的返回值类型
     */
    public interface StrategyMapper<T, R> {
        /**
         * 根据入参获取到对应的策略处理者。可通过 if-else 实现,也可通过 Map 实现。
         *
         * @param param 入参
         * @return 策略处理者
         */
        StrategyHandler<T, R> get(T param);
    }

    private StrategyMapper<T, R> strategyMapper;

    /**
     * 类初始化时注册分发策略 Mapper
     */
    @PostConstruct
    private void abstractInit() {
        strategyMapper = registerStrategyMapper();
        Objects.requireNonNull(strategyMapper, "strategyMapper cannot be null");
    }

    @Getter
    @Setter
    @SuppressWarnings("unchecked")
    private StrategyHandler<T, R> defaultStrategyHandler = StrategyHandler.DEFAULT;

    /**
     * 执行策略,框架会自动根据策略分发至下游的 Handler 进行处理
     *
     * @param param 入参
     * @return 下游执行者给出的返回值
     */
    public R applyStrategy(T param) {
        final StrategyHandler<T, R> strategyHandler = strategyMapper.get(param);
        if (strategyHandler != null) {
            return strategyHandler.apply(param);
        }

        return defaultStrategyHandler.apply(param);
    }

    /**
     * 抽象方法,需要子类实现策略的分发逻辑
     *
     * @return 分发逻辑 Mapper 对象
     */
    protected abstract StrategyMapper<T, R> registerStrategyMapper();
}

2. 创建策略处理器接口

package com.li.myspringbootmybatis.strategy;

/**
 * @author
 * @date
 */
public interface StrategyHandler<T, R> {

    @SuppressWarnings("rawtypes")
    StrategyHandler DEFAULT = t -> null;

    /**
     * apply strategy
     *
     * @param param
     * @return
     */
    R apply(T param);
}

3.  开始构建对应的节点信息

*           +---------+
*           |  Root   |   ----------- 第 1 层策略入口
*           +---------+
*            /       \  ------------- 根据入参 P1 进行策略分发
*           /         \
*     +------+      +------+
*     |  A   |      |  B   |  ------- 第 2 层不同策略的实现
*     +------+      +------+
*       /  \          /  \  --------- 根据入参 P2 进行策略分发
*      /    \        /    \
*   +---+  +---+  +---+  +---+
*   |A1 |  |A2 |  |B1 |  |B2 |  ----- 第 3 层不同策略的实现
*   +---+  +---+  +---+  +---+

4.  创建Root

package com.li.myspringbootmybatis.strategy.root;

import com.li.myspringbootmybatis.strategy.AbstractStrategyRouter;
import com.li.myspringbootmybatis.strategy.StrategyHandler;
import com.li.myspringbootmybatis.strategy.a.A;
import com.li.myspringbootmybatis.strategy.b.B;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@Component
public class Root extends AbstractStrategyRouter<String,Boolean> {
    @Resource
    private A a;

    @Resource
    private B b;
    /**
     * 定义用来存储执行策略的map集合
     */
    private Map<String,StrategyHandler> strategyMap = new HashMap();

    /**
     * 创建某个节点下的策略或节点
     * @return
     */
    @Override
    protected StrategyMapper<String,Boolean> registerStrategyMapper() {
        strategyMap.put("A",a);
        strategyMap.put("B",b);
        return new RootStrategyMapperImpl();
    }

    /**
     * 实现父类定义的接口,用于实现自己的获取不同的策略
     * 就像文章中所说,可以写if也可以写map,在这我们使用的是map
     */
    class RootStrategyMapperImpl implements StrategyMapper<String,Boolean>{

        @Override
        public StrategyHandler<String,Boolean> get(String param) {
            return strategyMap.get(param);
        }
    }
}

5. 创建A 

package com.li.myspringbootmybatis.strategy.a;

import com.li.myspringbootmybatis.strategy.AbstractStrategyRouter;
import com.li.myspringbootmybatis.strategy.StrategyHandler;
import com.li.myspringbootmybatis.strategy.b.B;
import com.li.myspringbootmybatis.strategy.root.Root;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
@Component
public class A extends AbstractStrategyRouter<String,Boolean> implements StrategyHandler<String, Boolean> {

    /**
     * 定义用来存储执行策略的map集合
     */
    private Map<String,StrategyHandler> strategyMap = new HashMap();

    @Override
    protected StrategyMapper<String,Boolean> registerStrategyMapper() {
        strategyMap.put("A1",new A1());
        strategyMap.put("A2",new A2());
        return new AStrategyMapperImpl(strategyMap);
    }

    /**
     * 实现自己获取 对应的策略信息
     */
    class AStrategyMapperImpl implements StrategyMapper<String,Boolean>{

        private Map<String,StrategyHandler> strategyMap1;
        AStrategyMapperImpl(Map map){
            strategyMap1 = map;
        }

        @Override
        public StrategyHandler<String,Boolean> get(String param) {
            return strategyMap1.get(param);
        }
    }

    @Override
    public Boolean apply(String param) {
        System.out.println("A执行。。。。");
        System.out.println("A执行完毕");
        //用于责任链调用,传递执行A1策略
        this.applyStrategy("A1");
        return true;
    }
}

6. 创建A1节点

package com.li.myspringbootmybatis.strategy.a;

import com.li.myspringbootmybatis.strategy.StrategyHandler;
import org.springframework.stereotype.Component;

@Component
public class A1 implements StrategyHandler<String,Boolean> {
    @Override
    public Boolean apply(String param) {
        System.out.println("A1开始执行");
        System.out.println("A1开始完毕");
        return true;
    }
}

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值