00:00
Java设计模式之命令模式。看一下。我们还是用一个需求引出我们要讲解的命令模式。先看这样一个需求,叫智能生活项目需求。那现在呢,我们有这样一个。有,有这样一套智能家电,有照明灯、风扇、冰箱、洗衣机。那现在呢,这些设备我们都装的有在手机上呢,我们都做安装一个APP,对,那么安安装这个APP呢,我们就可以对这些家电进行一个控制,这是第一个需求,第二个呢。我们这个智能家电来自不同的厂商。所以说我们不想针对每一种家电都安装一个APP,怎么个意思呢?就是说我们不能说照明灯,咱们装一个APP去控制它。风扇,我们装一个APP去控制它,这样太多了。对不对,所以说我们希望呢,只要安装一个APP,就可以控制全部的这个智能家电。
01:01
其实大家有没有发现这个很像我们的。前面讲的外观模式,但是呢,又有不同的地方,待会儿大家注意听这个哈。我们要实现一个APP控制所有智能家电的需求,则每个家电,每个智能家电厂商只要提供。一个统一的接口给我们APP调用就行了。因为我们这个地方呢,要么是关,要么是开,要么是撤就撤销这个操作,所以说这时呢,我们就可可以考虑命令模式。那么mini模式呢?可以将动作的请求者和动作的执行者。金结。就是一个是请求者,一个是。这个。叫做执行者,把它分开,通过什么呢?通过这个命令把他们关联起来。所在我们这个例子中呢,动作的请求者就相当于是手机的APP,而动作的执行者呢,就是每个厂商的家电。这样讲了,我相信大部分同学还是不太明白这个命令模式是怎么用的,我们来看一下啊,各位。
02:05
那么我们对命令模式呢?做一个基本的介绍,命令模式也叫command。他在软件,他在软件设计中呢,我们需要经常对某些对象发送请求,但是我们并不知道请求的接收的是谁,就这个接收接收者我们可能不太清楚。也不知道被请求的操作是哪一个。这时,我们只需要在程序运行中指定具体的请求接收者就可以了。然后这时呢,我们可以通过命令模式,你比如说。我们有一个将军,他要去命令这个士兵打仗,那怎么办呢?我们传递一个命令。就说其实他他都这个将军都不一不一定知道是哪一个士兵去打仗,他只要传达一个命令说进攻。然后这个命令被谁接收到呢?被我们这个小这个士兵接收到,士兵就去打了,其实命令的发布者他并不知道是谁来执行的。
03:07
大家明白我在说什么吗?因为我们这个地方可以通过我们这这的一个衔接,这个就是我们的命令。来,把它关联起来就行了,说我发布一个命令进攻。比如说我说1000个士兵,100个士兵进攻,把这个命令一传达下去,那么下面由这个命令去操控相关的人员执行就可以了。他是这么一种逻辑,也就是说他能够把命令的这个发布者和命令的执行者解开。那我们传统的方法可能是。这个将军这样子,张三进攻,李四进攻,这样太麻烦了。因为你想一想你。你,你假如说这个将军管了一一百个人。100个人。他如果说给给100个人士兵都分别下命令,太累了,比如说。这个敌人进攻了啊,有有个敌人向我们来了,然后这个将军说张三进攻,李四进攻,王五进攻,这什么一堆队啊,就发布命令都发布了100个,累不累啊,太累了,那怎么办呢?OK,那这样子他就把这个命令传递给他的另外一个助手,比如说他的。
04:17
呃,一个命令接接接收员。对吧,或者他的秘书说,我告诉你,我要100个人。立即向某某山头进攻,好这个,他的助手得到这个命令过后,由他去协调就完事了。是这么一种逻辑,这么一种逻辑好了,所以说命令模式呢,它它使得请求发送。者和请求接收者相互之间解耦,让对象之间的调用关系呢更加的灵活。之间结耦这样一个效果,在命令模式中会将一个请求封装成一个对象,也就是说我们可以把一个命令当成一个对象了。呃,这个对象里面可能包含一些信息,就他这个命令里面都包含了一些信息,传达给接收者就行了。
05:02
好的,那这个时候呢,可因为它封装成一个对象,以便使用不同的参数来表示不同的命令,同时命令模式呢,也支持撤销啊,它是一定要支持撤销的,比如说我发布一个命令,说100个市民进攻,突然我发现诶不对。我要把这个命令撤销一下,也是允许的。这个命令模式必须支持可撤销的这个功能,才算是一个比较严谨的命令模式。注意,听好,那么我们可以这样通俗的理解,将军发布一个命令,士兵去执行,其中有几个角色就出来了。首先呢,将军,士兵注意,将军他不是直接去指挥这个士兵的。他干什么呢?他用这个命令就是他其实将军发布的是一个命令,这个命令里面包含了一系列信息。OK。好,命令呢,它是连接,将它连接的将军和士兵。好,从这面我们分布几个角色,Invoer就是调用者,叫将军,Invoer呢就是我们命令模式里面的一个角色,叫调用者,所以CR呢就是被调用者,你可以理解成是施兵。还有一个my command就是命令,它会实现command接口。
06:12
持有这个command里面呢,它持有或者叫做呃,聚合的有我们这个接收者。好,这样子我相信听了大概有点印象,就就感觉好像哦,我们有一个人发布一个命令,把把信息,把命令具,把命令具体的命令写到一个对象里面,由我们这个接,由这个执行的去执行就完了,实现结果,那现在呢,我们画一个图,大家就更清晰的理解来,我们呢,为了让大家。对这个命令模式理解的更到位一点。我们画一个。原理图原理类图,加深大家对它的认识,好朋友们,我我现在呢,在这个地方我们新建一个包。新建一个包,这个包呢,我们就叫command。
07:03
OK,那在command里面呢,我们新建一个类图没问题。Class。一个类图。那怎么画呢?同学们看,首先我们会有一个命令,命令一般来讲会做成一个接口。OK。当然这个命令里面呢,它必须有两个属性,有两个方法,一个是执行。Ex exe cut,好,至于执行什么命令,到时间由你来在下面的子类具体去实现。还有一个命令呢,就是可以撤销我们的命令,我们讲过命令模式必须要支持这个所还有一个undo。这是一个接口,看清楚了。那么这个接口完了,下面呢,我们就有一个具体的命令,我写个叫康。什么呀,Command。好的,这是这是我们command的一个具体的一个实现了。那所以说他要去实现我们这个接口。
08:00
所以实现这个接口说的再直接一点,这里面呢,各位同学注意听哈,这里面就会要去实现上面的SQ的这个方法,还有undo这个方法。但是我讲过XQ这个方法和undo方法到底是什么,有你的这一个,Com的这个,对这个。这个对象里面包包或者持有的那个执行者来具体的完成。那就意味着这个,Com,呃,Concrete command里面呢,必须有这么一个东西,就是什么呢?我们的命令的接收者或者叫执行者都可以receiver re。它这里面呢,会有一些相应的动作。比如说他有action。当然我说了这个action这个名字呢,这个方法可能是,呃,不一定叫action,可能叫比如说connect呀,或者是select呀,或者是在爱呀等等,那么这个receiver呢,它会干什么呀,会被聚合到我们这个。
09:03
里面去,也就是说这个具体的一个command,呃concrete command呢,它聚合了我们这个receiver,同时呢,它实现这个接口,那大家可以想象到,那当我要去执行的时候,这个SQ的到底执行的是哪个,是不是就有就调用这个reserve里面的某一个方法。大家明白我在说什么吗?就说对他来讲呢,他就是个执行,至于至至于这个执行到底是执行什么,由你这个具体实现的这个子类去决定,你这个业务逻辑是什么,可能是调用这个receiver的。Action方法,也可能调用他的爱的方法,也可能调用他的另外一个方法。至于你聚合的是哪一个receiver,跟你这个业务逻辑也有相关的关系,因为它下面可能有多个concrete command。好,最后呢,我们还有一个调用者,来看调用者是谁呢,Invoker。注意听,就是刚才我们说的命令的,呃,调用者啊调调用者吧。
10:02
那么调动着以前我们是干什么呀?我们是直接让他去调这个家伙的,是这样子吧,同学们现在不这样了。干什么呢?OK,我呢?把这个command聚合到我这里面就可以了,当然它是通过这个接口聚合的一个concrete command。那也就是说,对于invoer来讲呢,它其实就是发布一个命令,而这个命令里面他去决定到底怎么干这个事。大家发现没有,这就实现了我们命令的调用者和命令的接收者或者叫执行者解耦了,通过谁来解耦?通过这个哥们也有。OK。而且同时呢,我们这个invoker里面是通过这个接口跟我们这个concrete command发生了一个依赖。或者说关联。好,那对于我们兰来说怎么用呢?各位朋友就说我们可定要去用它嘛,那兰呢,它去用这个invoer就可以了,当然它也可能会用到receiver,他会干什么呢?他会在这个client里面,它会创建receiver,再创建一个invoer,然后把receiver和invoer通过这个command关联起来就行了。
11:13
好,这个就是我们什么呀,一个叫做命令,命令模式的。一个原理类图,大家看你理解了没?主要是看这个地方invoc receiver呢,解耦了,通过谁来解呢?通过这个哥们解耦。好,同学们,那关于这个命令模式的原理类图,我们就先说到这儿,那么我把这个类图画到这来。我我把这个对图直接放过来,同学们。好的。放到这来以后呢,我们对同学们,我们对这个原理类图,再对他的角色,我们再做一些说明,加深大家的认识。好吧,来走一个,首先我们说一下invoer是什么invoer。就是他是调用者的角色。调用者。角色。
12:01
调用的角色,他干什么呢?呃,他是相当是要求该命令。就就是调用者啊,就调用者就可以了,还有一个command,同学们看到这个command。这个command是什么呢?是命令角色。命令角色,OK,他需也就说是需要执行的所有。所有命令都在这里。命令都在。都在这里。OK,都在这里,可以是接口,也可以是抽象类,可以是接口或。或什么呢,抽象类。那还有一个是什么呀,就是同学们看到receiver。Re s这个是什么呢?是接收者的角色,接收者。呃,就是接收者。角色。那么这个接收者角色,他是干什么呢?他是知道,他是知道如何实施。
13:04
如何实施和执行,执行一个请求相关的。相关的操作他是知道的,也就是说他其实是一个具体的。OK,它是一个具体来执行的,那么第三点大家可以看到的是concrete,这个command。那么这个是个什么东西呢?同学们,它是将注意听将一个接收者。接收者和和和和接收者,他是将一个接受者对象干什么呢?与一个动作。动作或者说一个命令啊,或者是调用。调用接收者。调接收。调用接收者,OK,调用收者相应的操作实现什么呢?实现执行s q exe Co,也就是说他干什么?Concrete command,它是将一个对象,接收者对象和一个动作绑定,这样写吧,加一个绑定就行了。
14:13
绑定,然后呢,调用接收者相调用接受者相应的操作实现SQ的,也就是说这个地方诶不好意思。这个地方。这里看到了。诶,这个怎么回事儿。嗯。好,待待会再说啊,这个快捷键不知道怎么用不了了,就说这个concrete,它是这里面把接收者聚合进去了,同时呢,他把一个执行的动作也绑定了,那这样子调用调用的这个接收者,他是调用接收者相应的操作实现XQ的。也就说你发一个命令给我,你发了一个命令给我,那么这个SQ里面到底执行哪这个receiver的哪一个操作呢?由他来决定。
15:00
其实这个地方是一个比较关键的,对不对啊,所以说他是这么一个,它是将一个接收者对象和动作绑定,然后调用接收者的一个操作完成这个任务。好,同学们,那关于我们这一个就是命令模式的原理,我们就先聊到这儿,那命令模式的原理我们说完了,下面我们自然就来做一个应用实例,来加深对命令模式的理解。
我来说两句