zoukankan      html  css  js  c++  java
  • 命令模式

    命令模式是一种高内聚的模式,定义为:将一个请求封装为一个对象,从而使不同的请求把客户端参数化,将请求排队或记录请求日志,可以提供命令的撤销和恢复功能。

    命令模式通常有三个角色:

    • Receiver接收者角色。接收到命令后执行具体任务
    • Command命令角色。需要执行的所有命令都在这里定义
    • Invoker调用者角色。接收到命令,并执行命令

    下面看一段通用代码:

    //接收者,可以是多个,所以定义为抽象类
    public abstract class Receiver{
        //抽象接收者,定义每个接收者必须完成的任务
        public abstract void doSomething();
    }
    //具体的接收者
    public class ConcreateReceiver1 extends Receiver{
        //处理逻辑
        public void doSomething(){}
    }
    public class ConcreateReceiver2 extends Receiver{
        //处理逻辑
        public void doSomething(){}
    }
    //抽象的Command类
    public abstract class Command{
        //每个命令类都必须有一个执行命令的方法
        public abstract void excute();
    }
    //具体的Command类,通过构造函数确定是针对哪个接收者发出的命令
    public class ConcreateCommand1 extends Command{
        //对哪个receiver类进行命令处理
        private Receiver receiver;
        //构造函数接收者
        public ConcreateCommand1(Receiver receiver){
            this.receiver = receiver;
        }
        //必须实现一个命令
        public void excute(){
            this.receiver.doSomething();
        }
    }
    public class ConcreateCommand2 extends Command{
        //对哪个receiver进行命令处理
        private Receiver receiver;
        public ConcreateCommand2(Receiver receiver){
            this.receiver = receiver;
        }
        //必须实现一个命令
        public void excute(){
            this.receiver.doSomething();
        }
    }
    //调用者类,仅实现命令的传递
    public class Invoker{
        private  Command command;
        //受气包,接收命令
        pubulic void setCommand(Command command){
            this.command = command;
        }
        //执行命令
        public void action(){
            this.command.excute();
        }
    }
    //场景类
    public class Client{
        public static void main(String[] args){
            //首先声明调用者
            Invoker invoker = new Invoker();
            //定义接收者
            Receiver receiver = new ConcreateReceiver1();
            //定义命令,指定接收者
            Command command = new ConcreateCommand(receiver);
            //把命令交给调用者执行
            invoker.setCommand(command);
            invoker.action();
        }
    }

    命令模式的优点:

    • 类间解耦。调用者和接收者没有任何依赖关系,调用者只需要调用Command抽象类的excute方法就可以,不需要了解是哪个接收者执行
    • 可扩展性。Command的子类非常容易扩展,而调用者不会和更高层模块耦合
    • 可以结合其他模式取得更好的表现。和责任链模式组合实现命令族解析任务;和模板方法模式组合减少Command子类膨胀问题

    命令模式缺点:

      使用不当,会产生command子类膨胀的问题。

    应用场景:

      所有你认为是命令的地方都可以使用。比如GUI的点击任务,DOS窗口的模拟命令等。

    最佳实践:

      在通用示例中,Receiver角色暴露给了Client类!这是不应该存在的依赖,实际应用中,receiver模块一般会被封装掉(除非必要,比如有撤销处理),下面展示优化的例子:

    public abstract class Command {
        //定义一个子类的全局共享变量
        protected final Receiver receiver;
        //实现类必须定义一个接收者
        public Command(Receiver _receiver){
            this.receiver = _receiver;
        }
        //每个命令类都必须有一个执行命令的方法
        public abstract void execute();
    }    
    public class ConcreteCommand1 extends Command {
        //声明自己的默认接收者
        public ConcreteCommand1(){
            super(new ConcreteReciver1());
        }
        //设置新的接收者
        public ConcreteCommand1(Receiver _receiver){
            super(_receiver);
         }
        //每个具体的命令都必须实现一个命令
        public void execute() {
            //业务处理
            super.receiver.doSomething();
        }
    }
    public class ConcreteCommand2 extends Command {
        //声明自己的默认接收者
        public ConcreteCommand2(){
            super(new ConcreteReciver2());
        }
        //设置新的接收者
        public ConcreteCommand2(Receiver _receiver){
            super(_receiver);
        }
        //每个具体的命令都必须实现一个命令
        public void execute() {
            //业务处理
            super.receiver.doSomething();
        }
    }    
    public class Client {
        public static void main(String[] args) {
        //首先声明调用者Invoker
        Invoker invoker = new Invoker();
        //定义一个发送给接收者的命令
        Command command = new ConcreteCommand1();
        //把命令交给调用者去执行
        invoker.setCommand(command);
        invoker.action();
        }
    }
  • 相关阅读:
    .net core获取数据库连接 抛出The type initializer to throw an exception
    解决本地Bootstrap字体图标不可见的问题
    Bootstrap 遮罩插件jquery.mloading
    oracle 数据库触发器,插入更新时间戳
    入门wpf—— 3、样式
    VisualStudio 连接 MySql 实现增删查改
    Bootstrap-table 使用总结,和其参数说明
    oracle数据库 TIMESTAMP(6)时间戳类型
    3.xadmin配置
    2.Model设计
  • 原文地址:https://www.cnblogs.com/loveBolin/p/9716120.html
Copyright © 2011-2022 走看看