命令模式是为了将调用者和执行进行解藕,所以引入了中间层命令,下面举一个例子,我们实现一个可以播放磁带的磁带机,然后用它来播放磁带。

中介者模式是用来降低多个对象和类之间的通信复杂性,这种模式提供了一个中介类,同过该类来处理不同类之间的通信,并支持松耦合,使代码便于维护。

1 上代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// 首先定义一下命令
public interface Command {
    void execute();
}

// 定义一下磁带格式
public interface Tape {

    /**
     * 播放磁带
     */
    void playTape();

    /**
     * 停止播放磁带
     */
    void stopTape();
}

// 实现播放命令
/**
 * 播放磁带
 */
public class PlayTapeCommand implements Command {

    private Tape tape;

    public PlayTapeCommand(Tape tape) {
        this.tape = tape;
    }
    
    @Override
    public void execute() {
        tape.playTape();
    }
}

// 实现停止命令
/**
 * 停止播放磁带
 */
public class StopTapeCommand implements Command {

    private Tape tape;

    public StopTapeCommand(Tape tape) {
        this.tape = tape;
    }

    @Override
    public void execute() {
        tape.stopTape();
    }
}

// 实现磁带机
/**
 * 磁带机
 */
public class MagneticTapeStation {

    private PlayTapeCommand playTapeCommand;
    private StopTapeCommand stopTapeCommand;

    public void setTape(Tape tape) {
        this.playTapeCommand = new PlayTapeCommand(tape);
        this.stopTapeCommand = new StopTapeCommand(tape);
    }

    /**
     * 按下播放按钮
     */
    public void pressPlayButton() {
        playTapeCommand.execute();
    }

    /**
     * 按下停止按钮
     */
    public void pressStopButton() {
        stopTapeCommand.execute();
    }
}

// 测试播放磁带有没有问题
public class Main {
    public static void main(String[] args) {
        // 先 new 出我们的磁带机
        MagneticTapeStation magneticTapeStation = new MagneticTapeStation();
        // 第一盘磁带,里面的内容是周杰伦的等你下课
        Tape tape1 = new Tape() {
            @Override
            public void playTape() {
                System.out.println("播放等你下课");
            }

            @Override
            public void stopTape() {
                System.out.println("停止播放等你下课");
            }
        };
        // 第二盘磁带,里面的内容是周杰伦的告白气球
        Tape tape2 = new Tape() {
            @Override
            public void playTape() {
                System.out.println("播放告白气球");
            }

            @Override
            public void stopTape() {
                System.out.println("停止播放告白气球");
            }
        };
        // 我们先放入第一盘磁带
        magneticTapeStation.setTape(tape1);
        // 按下播放按钮
        magneticTapeStation.pressPlayButton();
        // 按下停止按钮
        magneticTapeStation.pressStopButton();

        // 我们先放入第二盘磁带
        magneticTapeStation.setTape(tape2);
        // 按下播放按钮
        magneticTapeStation.pressPlayButton();
        // 按下停止按钮
        magneticTapeStation.pressStopButton();
    }
}

关于这个命令有一个疑惑,策略模式完全可以做到这件事,在中间加一层看上去有点多余。后面结合 Hystrix 的实现来理解这样做的好处吧。

很多帖子上说命令模式和策略模式的不同,其中提到策略模式没有接收者,我觉得吧,策略模式所实现的不同的策略就是接收者,不过是换个名字而已,说到底就是哪个类是真正干活的,接收者在命令模式里面是那个真正干活的,策略模式的具体策略也是那个具体干活的,这不就是同一个东西么,说一他们说的策略模式里没有接收者我是不认同的。

不过我倒是想到一点不同,策略模式里面的策略在什么地方调用都定死了,但是命令模式有所不同,命令这个概念被抽象出来了,那么我们就可以在需要的地方让命令排队,这个策略模式还真做不到。

参考资料

  1. 《JAVA 与模式》之命令模式