美文网首页设计模式笔记
设计模式笔记(六): 命令模式

设计模式笔记(六): 命令模式

作者: yeonon | 来源:发表于2018-07-25 14:49 被阅读13次

    命令模式是什么呢?考虑一下电视遥控器的场景,我们按下遥控器的某个按键,电视就会有相应的反应(例如换台)。按下遥控器就想是人发起了一个命令,遥控器接受了这个命令,并将其转发给电视,最后电视处理这个命令,并作出响应。整个过程中,遥控器并不知道请求的具体内容,即它不知道人类是想要换台呢,还是调节音量等等,它不关系这些东西而只需要将命令完整的转发给电视机即可。

    那为什么还需要这个遥控器呢?人类完全可以直接操作电视机的嘛(注意电视机上提供的按钮其实也属于遥控器)。确实可以,但是这样一来,人类和电视机之间的联系太紧密了,即耦合度高。如果现在电视机的实现变了,人类就不得不重新学习如何操作电视机,而如果用遥控器的话,人类只需要熟悉遥控器上的按钮,即使电视机的实现改变了,只要其接口没变,遥控器都能很好的工作。

    命令模式的实现

    下面是上述场景的简单代码实现:

    //电视类
    public class TV {
    
        public void doChange() {
            System.out.println("change TV");
        }
    }
    
    //命令接口和实现类
    public interface Command {
        void execute();
    }
    public class ChangeCommand implements Command {
        //需要指定该命令的接受对象
        private TV tv;
    
        public ChangeCommand(TV tv) {
            this.tv = tv;
        }
    
        @Override
        public void execute() {
            this.tv.doChange();
        }
    }
    
    //遥控器类
    public class Controller {
    
        //这里Commond可以设置为数组,使其支持多个命令,这里为了简单,直接单个命令了
        private Command command;
    
        public void setCommand(Command command) {
            this.command = command;
        }
    
        public void action() {
            this.command.execute();
        }
    }
    
    //客户端
    public class Client {
    
        public static void main(String[] args) {
            TV tv = new TV();
            Command changeCommand = new ChangeCommand(tv);
            Controller controller = new Controller();
            controller.setCommand(changeCommand);
            controller.action();
        }
    }
    

    运行程序,可以得到如下结果:

    change TV
    

    显然,这是我们想要的结果。

    命令模式剖析

    命令模式分为五个部分:

    1. Client客户端(Client)
    2. Command接口 (Client)
    3. Command实现类 (ChangeCommand)
    4. invoker调用者(遥控器)
    5. Recevier接受者(TV)

    类图如下所示:


    命令模式类图

    命令模式的特点

    命令模式很适合命令-响应的场景,其扩展性和复用性都很好,我们可以添加很多命令类,而且这些命令类可以相互组合形成一个更复杂的命令。即后面的扩展往往是建立在已有的命令类上进行的,这就使得其复用性很好。

    其封装性也比较好,其实整个模式算是有两次封装,一次是在invoker里调用命令的execute()方法,另一次是在command的实现类里调用Receiver里的具体方法。(上述例子中是doChange()方法)。这样使得客户端只需要知道命令的实现类是怎样就可以了,完全不用关系Receiver(TV)是如何实现的,也不用关心Invoker(遥控器)是怎么实现的。

    命令模式的缺点主要是可能会导致命令类很多,而且如果命令很简单,那么这个类可能只有几行代码,如果不加限制可能导致“类爆炸”。

    小结

    现在可以给出命令模式的定义了:命令模式将请求封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。

    本系列文章参考书籍是《Head First 设计模式》,文中代码示例出自书中。

    相关文章

      网友评论

        本文标题:设计模式笔记(六): 命令模式

        本文链接:https://www.haomeiwen.com/subject/hdjpmftx.html