Loading

设计模式-责任链模式

责任链模式

一个请求的处理分为多个阶段,每个阶段作为责任链的一个节点,节点各自处理自己责任范围内的请求.

场景:发起审批,包括审批理由和审批金额

首先定义一个请求

public class Request {
    private String reason;

    private BigDecimal amount;

    public Request(String reason, BigDecimal amount) {
        this.reason = reason;
        this.amount = amount;
    }

    @Override
    public String toString() {
        return "Request{" +
                "reason='" + reason + '\'' +
                ", amount=" + amount +
                '}';
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }
}

定义统一的处理接口

/**
 * 提供一个统一的处理接口
 */
public interface Handler {
    // 返回Boolean.TRUE = 成功
    // 返回Boolean.FALSE = 拒绝
    // 返回null = 交下一个处理
    Boolean process(Request request);
}

具体的处理实现类

@Slf4j
public class BossHandler implements Handler {
    @Override
    public Boolean process(Request request) {
        log.info("Boss handler");
        if (request.getReason().equalsIgnoreCase("recruit")) {
            log.info("不想招人...")
            return false;
        }
        return true;
    }
}

另一个处理节点

@Slf4j
public class ManageHandler implements Handler {
    @Override
    public Boolean process(Request request) {
        if (request.getAmount().compareTo(BigDecimal.valueOf(1000L)) > 0) {
            return null;
        }
        log.info("manager handler");
        return !request.getReason().equalsIgnoreCase("party");
    }
}

客户端调用

@Slf4j
public class Client {
    public static void main(String[] args) {
        List<Handler> handlers = new ArrayList<>();
        handlers.add(new ManageHandler());
        handlers.add(new BossHandler());

        Boolean result = null;

        // 外部控制责任链的逻辑,包括执行顺序,结果处理等
        for (Handler handler : handlers) {
            Request req = new Request("play", BigDecimal.valueOf(900));
            result = handler.process(req);
            if (null != result) {
                log.info(req + " " + (result ? "Approved by " : "Denied by ") + handler.getClass().getSimpleName());
                return;
            }
        }
    }
}

这里的实现是由外部控制责任链的执行,包括执行顺序和结果处理逻辑等.

结合Spring的实现

定义一个任务,它的执行过程中要经过各种校验,如时效性校验,风控校验,权限校验等流程

首先,定义一个任务类

public class Task {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

定义Filter接口

public interface Filter {
    boolean doFilter(Task task);
}

实现类

@Slf4j
@Component
public class AuthFilter implements Filter {
    @Override
    public boolean doFilter(Task task) {
        log.info("权限校验");
        return true;
    }
}
@Slf4j
@Component
public class DurationFilter implements Filter {
    @Override
    public boolean doFilter(Task task) {
        log.info("时效性校验");
        return true;
    }
}
@Slf4j
@Component
public class RiskFilter implements Filter {
    @Override
    public boolean doFilter(Task task) {
        log.info("风控校验");
        return true;
    }
}

将实现类交给Spring管理

服务调用

@Service
public class ApplicationService {

    @Autowired
    private List<Filter> filters;

    public void client() {
        Task task = new Task();
        task.setName("a task");

        for (Filter filter : filters) {
            boolean r = filter.doFilter(task);
            if (!r) {
                throw new RuntimeException("valid fail by " + filter.getClass().getSimpleName());
            }
        }
    }
}

这样如果需要添加新的过滤器,只要新增接口实现类即可。如果需要定义执行顺序,可以使用@Order注解定义类的加载顺序。

posted @ 2021-03-17 16:20  非凡岁月  阅读(54)  评论(0编辑  收藏  举报