Bootstrap

设计模式之命令模式

说实话这个模式挺令人纠结的,但从这个模式的定义上来看,有点让人摸不到什么头脑,而且查看资料以后会发现还是有点稀里糊涂的,说懂了吧也很简单,也不懂吧也有不懂的理由,于是查阅手头的各种书籍,在此写下心得体会,算是加深一下印象。

命令模式的定义:将请求封装成一个对象,从而让用户使用不同的请求把客户端参数化,以及支持可撤销和恢复的功能。

从定义上来看着实令人一脸懵逼,在这里描述一下博主个人的理解:

请求:客户端要求系统执行的操作,在java的世界里面就是某个对象的方法。

Command:请求封装成的对象,该对象是命令模式的主角。也就是说将请求方法封装成一个命令对象,通过操作命令对象来操作请求方法。在命令模式是有若干个请求的,需要将这些请求封装成一条条命令对象,客户端只需要调用不同的命令就可以达到将请求参数化的目的。将一条条请求封装成一条条命定对象之后,客户端发起的就是一个个命令对象了,而不是原来的请求方法!(行为参数化,在Java8得到了更好的支持)

Receiver:接受者,当然有命令的接收者对象:如果有只有命令,没有接受者,那不就是光棍司令了?没有电视机或者电脑主机,你对着电视机遥控器或者电脑键盘狂按有毛用?Receiver对象的主要作用就是受到命令后执行对应的操作。对于点击遥控器发起的命令来说,电视机就是这个Receiver对象,比如按了待机键,电视机收到命令后就执行了待机操作,进入待机状态。

Client:但是有一个问题摆在眼前,命令对象现在已经有了,但是谁来负责创建命令呢?这里就引出了客户端Client对象,再命令模式中命令是有客户端来创建的。打个比方来说,操作遥控器的那个人,就是扮演的客户端的角色。人按下遥控器的不同按键,来创建一条条命令。

Invoker:现在创建命令的对象Client也已经露脸了,它负责创建一条条命令,那么谁来使用或者调度这个命令呢?--命令的使用者就是Invoker对象了,还是拿人,遥控器,电视机来做比喻,遥控器就是这个Invoker对象,遥控器负责使用客户端创建的命令对象。该Invoker对象负责要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。

上面的讲解着实有些啰嗦,下面就用看电视的人(Watcher),电视机(Television),遥控器(TeleController)来模拟一下这个命令模式,其中Watcher是Client角色,Television是Receiver角色,TeleController是Invoker角色。

首先设计一个简单的电视机的对象:

//电视机对象:提供了播放不同频道的方法

public class Television {
   
    
    public void playCctv1() {
   
        System.out.println("--CCTV1--");
    }

    public void playCctv2() {
   
        System.out.println("--CCTV2--");
    }

    public void playCctv3() {
   
        System.out.println("--CCTV3--");
    }

    public void playCctv4() {
   
        System.out.println("--CCTV4--");
    }

    public void playCctv5() {
   
        System.out.println("--CCTV5--");
    }

    public void playCctv6() {
   
        System.out.println("--CCTV6--");
    }

}

电视机的类创建好了,本文会以“非命令模式“和“命令模式“两种实现看电视的不同之处,加深对命令模式的理解。

非命令模式实现:

如果不用命令模式的话,其实实现看电视的功能很简单,首先设计一个看电视的人的类:Watcher;既然要看电视,所以Watcher内部需要持有一个电视机的引用。如此简单的Watcher搞定:

//观看电视的死宅类
public class Watcher {
   
    //持有一个
    public Television tv;

    public Watcher(Television tv) {
   
        this.tv = tv;
    }

    public void playCctv1() {
   
        tv.playCctv1();
    }

    public void playCctv2() {
   
        tv.playCctv2();
    }

    public void playCctv3() {
   
        tv.
;