[design pattern](8) Command
前言
在前面的章节中,我们介绍了单例模式,它是创建型模式的一员。今天我们来介绍一下命令模式,它是行为型模式的一员。
思考题
首先,让我们来思考下面的问题:
话说有一家遥控器公司,他想制作一款很牛逼的遥控器。这个遥控器可以控制家里所有的电器,为了简单一点,假设所有的用户家里只有电视机和电灯两种电器。那么如果是你,你会怎么实现这个遥控器呢?
由于电视机和电灯是两个不同的厂商生产的产品,所以他们的打开方式是不一样的。首先让我们来看一看这两个类的定义:
Television.java:
public class Television { public void open() { System.out.println("打开电视"); } public void close() { System.out.println("关闭电视"); } }
ElectricLight.java:
public class ElectricLight { public void on() { System.out.println("打开电灯"); } public void off() { System.out.println("关闭电灯"); } }
让我们来看下下面的设计:
RemoteControl.java:
public class RemoteControl { private String product; public void setProduct(String product) { this.product = product; } public void execute() { switch (product) { case "Television": new Television().open(); break; case "ElectricLight": new ElectricLight().on(); break; default: } } }
这个遥控器太棒了,我可以用它来控制家里的电视机和电灯,再也不用到处翻找遥控器了。要是它还可以控制洗衣机那就更棒了。那么如果再在遥控器里添加一个洗衣机需要怎么做,哦,太糟糕了,我还需要把遥控器拆开,然后把洗衣机的命令添加进去,好痛苦有么有,那么有么有一种设计可以不对遥控器进行更改,就可以添加其他的家电呢。这个时候命令模式就可以发挥它的作用了。
命令模式
定义:将请求封装成对象,从而可以使用不同的请求将客户参数化,使得请求发送者和请求接受者之间互相隔离。
类图:
上面涉及到的角色有4个:
- 抽象命令:将命令封装成一个接口,每个接收者都需要实现一个相应的命令接口。
- 具体命令:实现了抽象命令类的方法,并且调用了具体接受者的方法。
- 请求接受者:具体要执行操作的类。
- 请求发送者:将命令对象传递给具体的接受者,执行相应的操作。
思考题实现
首先,定义一个抽象命令类:
Command.java:
public interface Command { void execute(); }
然后,实现抽象命令类:
TelevisionCommand.java:
public class TelevisionCommand implements Command { private Television television = new Television(); @Override public void execute() { television.open(); } }
ElectricLightCommand.java:
public class ElectricLightCommand implements Command { private ElectricLight electricLight = new ElectricLight(); @Override public void execute() { electricLight.on(); } }
然后,实现一个遥控器:
RemoteControl.java:
public class RemoteControl { private Command command; public void execute() { command.execute(); } public void initCommand(Command command) { this.command = command; } }
测试类:
Custom.java:
public class Custom { public static void main(String ...args) { RemoteControl remoteControl = new RemoteControl(); remoteControl.initCommand(new TelevisionCommand()); remoteControl.execute(); remoteControl.initCommand(new ElectricLightCommand()); remoteControl.execute(); } }