命令模式一

2022-10-02  本文已影响0人  三流之路

示例场景

// 接收者
public interface SonReceiver {
    public void pay(int money); // 交保护费
    public void bite(boolean b); // 咬人
    public void build(boolean b); // 军事基地建设
}

public class GuiZi implements SonReceiver {
    public void pay(int money) {
        System.out.println("上交保护费 " + money);
    }
    
    public void bite(boolean b) {
        if (b) {
            System.out.println("朝向东方某国竖中指,放狠话");
        } else {
            System.out.println("朝向东方某国,握手,我们是好朋友");
        }
    }

    public void build() {
        System.out.println("基地建设要不要放缓");
    }
}

public class BangZi implements SonReceiver {
    public void pay(int money) {
        System.out.println("上交保护费 " + money);
    }
    
    public void bite(boolean b) {
        if (b) {
            System.out.println("朝向东方某国,汪,汪汪");
        } else {
            System.out.println("朝向东方某国,喵,喵喵");
        }
    }
    public void build(boolean b) {
        System.out.println("基地建设要不要放缓 " + b);
    }
}

public class FatherDengTa {
    // 需要鞭策儿子了
    public void shouGuiZiBHF() {
        GuiZi gz = new GuiZi();
        gz.pay(5); 
        gz.bite(false); 
        gz.build(false);
    }

    public void shouBangZiBHF() {
        BangZi bz = new BangZi();
        bz.pay(1);
        bz.bite(true);
        bz.build(true);
    }
}

在例子中,爸爸亲自下场,和儿子要钱,爸爸只想要钱这么一个结果。

但是儿子一看要的有点多,就和爸爸商量你这有点狠啊,那我是不是得缓和一下和东方某国的关系,这样能多赚点钱,爸爸一听说也行,儿子又说,要缓和关系,那咱军事基地就得缓一缓,不能刺激人家,爸爸一听毛了,那不行,算了,那钱少收点,儿子说那成,我继续咬东方某国。

命令模式1.png

这样一件一件事来谈,会很繁琐,爸爸很忙,哪里有时间管这么多事。

中介者模式改造

所以想着也抽出一个中介,通过中介去做。和中介者模式感觉有那么一点像,但中介者是两两有交互,形成一个网状结构,是类间横向有关系,所以抽出一个中介者,变成星形状。这里像是类内点纵向关系,是一个方法就引起其它方法变化。

中介者模式.png

爸爸不想管了,爸爸说我不管这么多了,我就给你一个命令:交钱,你自己掂量。先类似中介的方法改造。

// 就不写抽象了
public class Mediator {
    private GuiZi gz = new GuiZi();
    private BangZi bz = new BangZi();
    
    public void execute(String str,Object...objects){ 
        if (str.equals("guiZi.pay")) {
            gz.pay((int)objects[0]); // 假设交得太多了
            gz.bite(false); 
            gz.build(false);
        } else if (str.equals("bangZi.pay")) {
            bz.pay((int)objects[0]); // 交得不是很多
            bz.bite(true);
            bz.build(true);
        }
    }
}

public class FatherDengTa() {
    private Mediator mediator;
    public FatherDengTa(Mediator _mediator){
        this.mediator = mediator;
    }  
    
    public void shouGuiZiBHF() {
        mediator.execute("guiZi.pay", 5)
    }

    public void shouBangZiBHF() {
        mediator.execute("bangZi.pay", 1)
    }
}

public class GuiZi {
    private Mediator mediator;
    public GuiZi(Mediator _mediator){
        this.mediator = mediator;
    }  

    public void pay(int money) {
        System.out.println("上交保护费 " + money);
    }
    
    public void bite(boolean b) {
        if (b) {
            System.out.println("朝向东方某国竖中指,放狠话");
        } else {
            System.out.println("朝向东方某国,握手,我们是好朋友");
        }
    }

    public void build() {
        System.out.println("基地建设要不要放缓");
    }
}

失败了,因为 GuiZi 作为底层的,不需要和其它交流,中介者给它也用不着。

命令模式改造

将命令封装成 Command,Command 本身就能明确哪个接收者该做什么事情。

public abstract class Command {  
    protected int money;
    public Command(int money) {
        this.money = money;
    }
    //接收者定义好
    protected GuiZi gz = new GuiZi(); 
    protected BangZi bz = new BangZi();
    // 只有一个执行方法
    public abstract void execute();
}

// 一个具体的命令本身,既能表明接收者是谁,又能表明需要做什么
public GuiZiPayCommand extends Command {
    public GuiZiPayCommand(int money) {
        super(money);
    }
    public void execute() {
        gz.pay(money);
        gz.bite(false);
        gz.build(false);
    }
}

// 类似中介,负责接收高层的命令,负责执行命令,命令一旦执行,就到了底层的接收者了
public class Invoker {
    private Command cmd;
    public void setCommand(Command command) {
        cmd = command;
    }
    public void action() {
        cmd.execute();
    }
}

public class FatherDengTa() {
    private Invoker invoker = new Invoker(); // 中介
    
    public void shouGuiZiBHF() {
        Command cmd = new GuiZiPayCommand(5);
        invoker.setCommand(cmd);
        invoker.action();
    }
}
命令模式2.png

特点

  1. 解耦,爸爸只需要把命令给执行者 Invoker,Invoker 只需要执行 Command,具体的逻辑都封装到 Command 内部去了。
  2. 方便扩展,多一件事情,只需要创建一个命令,修改命令对象的引用,其它都不需要改
  3. 当交互对象多了后,中介者会越大越复杂,这里也是,如果要做的事情多了后,每个都需要定义一个 Command,会越来越多,甚至感觉太细碎。
上一篇下一篇

猜你喜欢

热点阅读