设计模式——命令模式

一、定义

1、定义

创建一个命令对象来代表实际行动。命令对象可以把行动(action) 及其参数封装起来,于是这些行动可以被:

  • 重复多次
  • 取消
  • 取消后又再重做

这些都是现代大型应用程序所必须的功能,即“撤销”及“重复”。除此之外,可以用命令模式来实现的功能例子还有:

  • 交易行为
  • 进度列
  • 向导
  • 用户界面按钮及功能表项目
  • 线程 pool
  • 宏收录

2、UML类图

没有命令模式之前,调用者Invoker和被调用者Receiver是直接相连的,强耦合。

 

命令模式:下面这个类图取自维基百科。多了三个组件Client、Command及Command的实现类ConcreteConmmand

 

 自己画了一个UML类图:

 

 Invoker与Receiver通过Command解耦了,并且由client控制Invoker,Command,Receiver之间的关系

总结:命令模式有两个重要作用:

① 将请求封装成对象,将调用者与被调用者解耦

② 由于将请求封装成了对象,请求可以被重复使用(Command可被不同的对象使用,也可被同一个对象重复调用),另外还支持取消

所以:当需要发出请求的对象与执行请求的对象解耦的时候,使用命令模式。

3、简单实现

public class Light {

    private String addr;

    public Light(String addr){
        this.addr = addr;
    }

    public void on(){
        System.out.println(addr + " light on");
    }

    public void off(){
        System.out.println(addr + " light off");
    }
}

public interface Command {
    void execute();
    void undo();
}


public class LightOnCommand implements Command {

    private Light light;

    public LightOnCommand(Light light){
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }

    @Override
    public void undo() {
        light.off();
    }
}

public class Invoker {
    private Command command;

    public Invoker(Command command){
        this.command = command;
    }

    public void buttonWasPressed(){
        command.execute();
    }

}

public class Client {
    public static void main(String[] args) {
        Light light = new Light("room");
        LightOnCommand command = new LightOnCommand(light);
        Invoker invoker = new Invoker(command);
        invoker.buttonWasPressed();
    }
}

二、框架中的命令模式

 1、JDK中的线程池

前面已经有研究过线程池的源码

现在从命令模式的角度,看待一下线程池的实现。

当没有命令模式设计实现时,一个Thread只能执行一个任务

 线程池的设计,通过一个队列解耦Thread与Runnable的耦合关系,ThreadPoolExecutor就相当于client。

 

 

 

posted on 2020-04-15 20:08  FFStayF  阅读(339)  评论(0编辑  收藏  举报