设计模式--责任链模式&命令模式

631 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第33天,点击查看活动详情

责任链模式&吗&命令模式

责任链模式&命令模式,责任链模式适合处理存在链式算法的业务场景,将每一个场景抽象出来作为节点,可以灵活组合适应不同场景需要。命令模式模式是将命令发出者和命令执行者解耦,使得各自互不影响,提高代码健壮性

责任链模式

责任链模式(Chain of Responsibility),属于行为型模式。该模式存在多个对象每一个对象持有下一个对象的引用,这样就会形成一条链,直到某一对象决定处理该请求。对于客户端也就是调用者可以隐瞒内部实现。并且可以灵活的修改且不影响客户端调用逻辑。要求同一时刻命令只允许由一个对象传给另一个对象,而不允许同一时刻传给多个对象。

一般由于一些流程化的业务逻辑。

实现

定义抽象接口:

public interface Handler {
    /**
     * 做什么操作
     */
    void operate();
}

抽象父类:

@Data
public abstract class AbstractHandler {
    /**
     * 将对象组合进来
     */
    private Handler handler;
}

实现类:

@AllArgsConstructor
public class HandlerImpl extends AbstractHandler implements Handler {

    private String name;

    @Override
    public void operate() {
        System.out.println(this.name);
        final Handler handler = super.getHandler();
        if (!ObjectUtils.isEmpty(handler)) {
            handler.operate();
        }
    }
}

测试:

public class ChainOfResponsibilityTest {
    @Test
    public void test() {
        HandlerImpl handler1 = new HandlerImpl("1");
        HandlerImpl handler2 = new HandlerImpl("2");
        HandlerImpl handler3 = new HandlerImpl("3");
        HandlerImpl handler4 = new HandlerImpl("4");

        handler1.setHandler(handler2);
        handler2.setHandler(handler3);
        handler3.setHandler(handler4);
        handler1.operate();
    }
}
应用

生活中关于责任链模式的模型还是很多的。比如说买保险,保险公司对于保险的赔付率是由一定算法得出的。那么就是一条链下来某个节点触犯了条件那么就不可以买保险。

假设这里有一个保险公司的产品叫做“金致人生”,对于投保人有以下限制条件:

  • 年龄不大于80岁
  • 吸烟年龄小于10年
  • 不参加极限运动
  • 职业危险等级为 5 以下

那么我们就可以抽象出来,每一个条件都是责任链上的一个节点,就是一个handler


命令模式

命令模式(Command Pattern)属于行为模式,将一个请求封装为一个对象,使发出请求的责任与执行请求的责任分开。将命令发出者与命令接收者进行解耦,两者通过命令对象进行沟通。

包含角色

  • 抽象命令类(Command),定义命令抽象接口
  • 具体命令类(Concrete Command),抽象命令类的实现,将命令接受者组合进来,调用命令接受者的具体功能来完成命令的执行。
  • 命令接受者(Receiver),命令的具体执行者
  • 命令发出者或调用者(Invoker),命令发出者,将命令组合进来,通过调用命令来完成相关业务
实现

以公司领导安排任务为例。领导负责一个项目的进度,一般会有很多的员工,领导为多个员工下达不同的指令,员工负责具体执行对应任务。

在此模型中领导是命令发出者,员工是命令接受者,任务就是命令。领导无需关系任务具体完成细节,他只需要知道任务完成结果,每个任务分配给对应员工,员工具体执行业务。

抽像命令接口:

public interface Command {
    /**
     * 命令方法
     */
    void execute();
}

具体命令:将具体负责人组合进来

@Data
@AllArgsConstructor
public class ConcreteCommand implements Command {
    /**
     * 每个任务都有负责人
     */
    private Receiver receiver;
    @Override
    public void execute() {
        //具体负责人去完成任务
        receiver.doWork();
    }
}

命令接收者:

@Data
@Accessors(chain = true)
public class Receiver {
    String name;
    public void doWork() {
        System.out.println(this.name + "完成任务");
    }
}

命令发出者:

组合多个命令:

public class Invoker {
    /**
     * 老板将一个项目拆分为许多模块,每个模块就是一个命令
     */
    private List<Command> commandList = new ArrayList<>();
    public void addCommand(Command command){
        System.out.println("添加任务");
        commandList.add(command);
    }
    public void delCommand(Command command){
        System.out.println("移除任务");
        commandList.remove(command);
    }
    public void doCommand(){
        //完成任务
        commandList.forEach(Command::execute);
    }
}

测试:

public class Client {
    public static void main(String[] args) {

        Invoker invoker = new Invoker();

        Receiver receiver1 = new Receiver().setName("employee01");
        Receiver receiver2 = new Receiver().setName("employee02");
        Receiver receiver3 = new Receiver().setName("employee03");
        Receiver receiver4 = new Receiver().setName("employee04");

        Command command1 = new ConcreteCommand(receiver1);
        Command command2 = new ConcreteCommand(receiver2);
        Command command3 = new ConcreteCommand(receiver3);
        Command command4 = new ConcreteCommand(receiver4);

        invoker.addCommand(command1);
        invoker.addCommand(command2);
        invoker.addCommand(command3);
        invoker.addCommand(command4);

        invoker.doCommand();
    }
}

image-20220620122105520.png