首页 > 代码库 > 设计模式:学习笔记(3)——命令者式

设计模式:学习笔记(3)——命令者式

Java设计模式之命令者式

引入命令模式

案列

  比如我们要设计一个DOS命令模拟器,它可以接受输入的命令并做出响应。

  0.首先我们的DOS模拟器支持三个大类的功能:文件操作类(FileKit)、展示类(DisplayKit)、网络类(NetKit)

  1.建立抽象命令模板(默认所有的命令都可以使用上述三大类):

public abstract class Command {
    protected DisplayKit displayKit = new DisplayKit();
    protected FileKit fileKit =new FileKit();
    protected NetKit netKit = new NetKit();
    public abstract void execute();  //所有子类都需要实现这个执行方法
}

  2.编写具体命令:(这个就是命令的具体操作,可以看出是多个类协同合作的结果)

public class DeleteCommand  extends Command {
    public void execute() {
        displayKit.flushScreen();  //展示类:首先刷新一下屏幕
        fileKit.deleteFile();            //文件类:删除文件
        netKit.updateInfo();         //网络类:上传操作日志
        displayKit.flushScreen();  //展示类:再次刷新文件
    }
}

  3.编写调用器:(接受命令执行命令)

public class Invoker {
    private Command command;
    public void setCommand(Command command)  //传入命令
    {
        this.command=command;
    }
    public  void  action()       //调用命令的execute()方法
    {
        this.command.execute();
    }
}    

  4.客户端调用

public class Main {
    public static void main(String[] args) {
        Invoker MyDOS = new Invoker();  //建立调用器
        Command del = new DeleteCommand();  //建立命令
        MyDOS.setCommand(del);  //传入命令
        MyDOS.action();  //执行命令
    }
}

什么是命令模式

  说明:在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,实现二者之间的松耦合。这就是命令模式(Command Pattern)。[1] 

  通用类图:

  技术分享

说明:

● Receiver接收者角色
  该角色就是干活的角色, 命令传递到这里是应该被执行的。比如这里的文件操作类(FileKit)、展示类(DisplayKit)、网络类(NetKit)

● Command命令角色
  需要执行的所有命令都在这里声明。比如这里的
DeleteCommand。

● Invoker调用者角色
  要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。

模式分析

1.命令模式的本质是对命令进行封装,将发出命令的责任和执行命令的责任分割开
2.每一个命令都是一个操作:请求的一方发出请求,要求执行一个操作;接收的一方收到请求,并执行操作。
3.命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。
4.命令模式使请求本身成为一个对象,这个对象和其他对象一样可以被存储和传递。
5.命令模式的关键在于引入了抽象命令接口,且发送者针对抽象命令接口编程,只有实现了抽象命令接口的具体命令才能与接收者相关联。

模式优点

1.降低对象之间的耦合度。
2.新的命令可以很容易地加入到系统中。
3.可以比较容易地设计一个组合命令。
4.调用同一方法实现不同的功能

模式缺点

使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

最佳实践

  命令模式的Receiver在实际应用中一般都会被封装掉 , 那是因为在项目中: 约定的优先级最高, 每一个命令是对一个或多个Receiver的封装, 我们可以在项目中通过有意义的类名或命令名处理命令角色和接收者角色的耦合关系(这就是约定) , 减少高层模块(Client类) 对低层模块(Receiver角色类) 的依赖关系, 提高系统整体的稳定性。 因此, 建议大家在实际的项目开发时采用封闭Receiver的方法, 减少ClientReciver的依赖 。

  修改后的Command类:

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();
  }
}

 

说明一下:

  如果抽象类没有声明默认构造器的话,那么他的子类一定不能存在默认构造器。

 

设计模式:学习笔记(3)——命令者式