zoukankan      html  css  js  c++  java
  • 行为型之命令模式

    序言

      命令模式把发出命令的责任和执行命令的责任分隔开,分别委托给不同的对象。
    每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。
      命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
      使用命令模式会导致系统增加过度的具体命令类,使得其实现不切合实际。
      命令模式涉及到5个角色,分别是:

    • 命令角色:接口或者抽象类,抽象方法包含了命令的执行操作
    • 具体命令角色:类,实现命令的执行方法,调用接受者的相应操作
    • 请求者角色:类,负责调用命令的执行请求,相关的方法,叫行动方法
    • 接受者角色:类,负责具体实施和执行1个请求,相关的方法,叫行动方法

    命令模式

      电视机会有开机,关机,换台的基本命令操作,我们不需要知道其内部实现,在这里我们是客户端,而电视机可以被看做命令接受者,遥控器则可以被看做是命令请求者,我们只需要和请求者打交道即可。
      命令模式的结构如下图:

    ![](http://images2017.cnblogs.com/blog/946528/201708/946528-20170819100618818-561297377.png)
    >套路: >1. 将接受者要执行的命令拆分,分别创建对应的命令类,并把接受者对象委托到命令类中 >2. 创建请求者类,添加所有命令的委托对象,对于各自的命令,要创建各自的行动方法
    /**
     * 命令接受者-电视机
     */
    public class TV {
    
        private int currentChannel = 0;
        //行动方法
        public void trunOn(){
            System.out.println("电视机开启");
        }
        //行动方法
        public void turnOff(){
            System.out.println("电视机关闭");
        }
        //行动方法
        public void change(int channel){
            this.currentChannel = channel;
            System.out.println("切换到频道" + currentChannel);
    
        }
    }
    
    /**
     * 命令接口
     */
    public interface Command {
        public void execute();
    }
    
    /**
     * 打开命令
     */
    public class OnCommand implements Command{
    
        private TV tv;
        public OnCommand(TV tv){
            this.tv = tv;
        }
        public void execute() {
            tv.trunOn();
        }
    }
    
    /**
     * 换台命令
     */
    public class ChangeCommand implements Command{
        private TV tv;
        private int channel;
    
        public ChangeCommand(TV tv,int channel){
            this.tv = tv;
            this.channel = channel;
        }
    
        public void execute() {
            tv.change(channel);
        }
    }
    
    /**
     * 关闭命令
     */
    public class OffCommand implements Command {
        private TV tv;
    
        public OffCommand(TV tv){
            this.tv = tv;
        }
    
        public void execute() {
            tv.turnOff();
        }
    }
    
    /**
     * 复合命令,由多个连续的基本命令操作组成
     */
    public class ManyCommand implements Command{
    
        //可设计为命令队列
        private List<Command> commands = new ArrayList<Command>();
    
        public void add(Command command){
            commands.add(command);
        }
        public void remove(Command command){
            commands.remove(command);
        }
        public void execute() {
            for(Command command :commands){
                command.execute();
            }
        }
    }
    
    /**
     * 命令请求者-遥控器
     */
    public class Control {
    
        private Command offCommand;
        private Command onCommand;
        private Command changeCommand;
        private Command manyCommand;
    
        //行动方法
        public void turnOn(){
            onCommand.execute();
        }
        //行动方法
        public void trunOff(){
            offCommand.execute();
        }
        //行动方法
        public void change(){
            changeCommand.execute();
        }
        //行动方法
        public void exeManyCommand(){
            manyCommand.execute();
        }
    
        public void setOffCommand(Command offCommand) {
            this.offCommand = offCommand;
        }
    
        public void setOnCommand(Command onCommand) {
            this.onCommand = onCommand;
        }
    
        public void setChangeCommand(Command changeCommand) {
            this.changeCommand = changeCommand;
        }
    
        public void setManyCommand(Command manyCommand) {
            this.manyCommand = manyCommand;
        }
    }
    
    /**
     * 测试命令模式
     */
    public class CommandTest {
    
        @Test
        public void testCommand(){
    
            //命令接受者
            TV tv = new TV();
            //命令,绑定接受者
            OnCommand onCommand = new OnCommand(tv);
            ChangeCommand changeCommand = new ChangeCommand(tv, 3);
            OffCommand offCommand = new OffCommand(tv);
            //命令请求者,绑定命令
            Control control = new Control();
            control.setOnCommand(onCommand);
            control.setChangeCommand(changeCommand);
            control.setOffCommand(offCommand);
            //触发
            control.turnOn();
            control.trunOff();
            control.change();
    
            //复合命令
            ManyCommand manyCommand = new ManyCommand();
            manyCommand.add(onCommand);
            manyCommand.add(changeCommand);
            manyCommand.add(offCommand);
            //命令请求者绑定复合命令
            control.setManyCommand(manyCommand);
            //触发
            control.exeManyCommand();
        }
    
    }
    

    吹牛:

    1. 命令模式将对象的请求操作和执行操作分割开来,实现解耦
    2. 命令模式使新的命令很容易地被加入到系统里。
    3. 能较容易地设计一个命令队列。
    4. 可以容易地实现对请求的撤销和恢复。

    应用场景:

    • 可使用命令模式作为回调。先将行动方法注册上,然后在需要时调用。
    • 需要在不同的时间制定请求、将请求排队。1个命令对象和原先的请求发出者可以有不同的生命周期。换言之,原先的请求发出者可能已经不在了,而命令对象本身仍然是活动的。这时命令的接受者可以是在本地,也可以在网络的另外一个地址,命令对象可以在序列化之后传送到另外一台机器上去。

    后记

  • 相关阅读:
    转载一篇文章 python程序员经常犯的10个错误
    外部表与partition
    grpc 入门(二)-- 服务接口类型
    用例图简介(转)
    UML类图(Class Diagram)中类与类之间的关系及表示方式(转)
    快速搭建fabric-v1.1.0的chaincode开发环境
    ubuntu networking 与 network-manager
    [转]bashrc与profile区别
    超矩链--基于矩阵的分布式账本
    adb 在windows7中的使用
  • 原文地址:https://www.cnblogs.com/codebug/p/7395677.html
Copyright © 2011-2022 走看看