8.命令模式
命令模式即Command模式,此模式通过被称为Command的类封装了对目标对象的调用行为以及调用参数。将一个请求封装为一个对象,从而使我们可用不同的请求对用户进行参数化;对请求排队或记录请求日志,以及支持可撤销操作。
命令模式角色:
1.Command:定义命令的接口,声明执行的方法。
2.ConcreteCommand:命令接口实现对象,是“虚”的表现:通常会持有接收者,并调用接受者的功能来完成命令要执行的操作。
3.Receiver:接收者,真正执行命令的对象。任何类型都可能称为一个接收者,只要它能够根据命令要求实现的相应的功能。
4.Invoker:要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这是用户端真正触发命令并要求命令执行相应操作的地方,也就是说,相当于使用命令对象的入口。
5.Client:创建具体的命令对象,并且设置命令对象的接受者。注意这不是我们常规意义上的用户端,而是在组装命令对象和接受者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的用户端是从Invoker来触发执行。
点菜问题:本问题需要用宏命令来解决,什么是宏命令?简单的说就是包含多个命令的命令,这是一个命令组合。
下面是去饭店吃饭的一个模拟的过程。
(1)走进一家饭店,找到座位坐下。
(2)服务员走过来,递过来菜谱。
(3)开始点菜,服务员开始记录菜单,菜单是三联的,点菜完毕,服务员就会把菜单分成三份,一份给后厨,一份给收银台,一份保留备查。
(4)点完菜,坐在座位上等候,后厨会按照菜单做菜。
(5)每做好一份菜,就会由服务员送到餐桌上。
(6)此时就可以开吃了
事实上,在饭店点餐的过程就是一个很典型的命令模式应用。顾客只需要发出要吃什么菜的命令,每到菜就相当于一个命令对象,服务员会在菜单上记录所点的菜,然后把菜单传递给后厨,后厨拿到菜单,会按照菜单进行饭菜制作,后厨就相当于接收者,是命令的真正执行者,厨师菜知道每道菜具体怎么实现。
比如顾客点了凉菜和热菜,他其实是不知道到底凉菜由谁来完成,热菜由谁来完成,
因此他只管发命令,而组装的工作就由服务员来完成了。服务员知道做凉菜的命令送到凉菜部,那是已经做好了的,做热菜的命令送到后厨,那需要厨师现做。看起来服务员是一个组装者。同时服务员还持有命令对象,也就是菜单,最后启动命令执行的也是服务员。因此,服务员就相当于标准命令对象,也就是菜单,最后启动命令执行的也是服务员。因此服务员就相当于标准命令模式中Client和Invoker的融合。
当我们说点完菜的时候,服务员才会启动命令执行,但是这个命令是包含多道菜的大命令,
一个命令对象就相当于一道菜,那么这个菜单就相当于我们说的宏命令了。执行一个宏命令,简单点说就是执行宏命令里面所包含的所有命令对象,有点打包执行的感觉!
9.中介者模式
中介者模式:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。简单地说,将原来两个直接引用或者依赖的对象拆开,在中介加入一个“中介”对象,使得两头的对象分别与“中介”对象引用或者依赖。当然并不是所有的对象都需要加入“中介”对象。如果对象直接的关系原本一目了然,中介对象的加入便是“画蛇添足”了。
中介者模式的组成角色如下:
抽象中介者(Mediator)角色:抽象中介角色定义统一的接口,用于各同时角色之间的通信。
具体中介者(Concrete Mediator)角色:具体中介者角色通过协调各同事角色,实现协作行为,为此它要指导并引用各个同事角色。
同事(Colleage)角色:每一个同事角色都应该知道对应的具体中介者角色,而且与其他的同事角色通信的时候,一定要通过中介者角色协作。
例子:假如在一个公司里面有很多部门、员工(我们统称他们互相喂Colleague“同事”),为了完成一定的任务,“同事”之间肯定有许多需要互相配合、交流的过程。如果由各个“同事”频繁地到处去与自己有关的“同事”沟通,这样肯定会形成一个多对多的杂乱的联系网络,而造成工作效率低下。
此时就需要一位专门的“中介者”给各个“同事”分配任务,以及统一跟进大家的进度,并在“同事”之间实时地进行交互,保证“同事”之间必需的沟通交流。
很明显,我们知道此时的“中介者”是在“同事”之间担任沟通的重要角色,“中介者”使得每个“同事”都变成一对一的联系方式,减轻了每个“同事”的负担,增强了工作效率。
其实,中介者模式又被称为“调停者”模式,我们可以理解为一群小孩子(同事)吵架了,这时就很需要一位大人(调停者)过来处理好小孩子们的关系,以免发生不必要的冲突。“中介者”和“调停者”只不过是同一个英语单词Mediator的不同翻译。中介者是恰当的处理众多对象相互之间的联系的角色。
10.备忘录模式
备忘录模式又被称为标记(Token)模式。备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
由定义可知,备忘录模式是专门用来存放对象历史状态的,这对于很好地实现undo、redo功能有很大的帮助。所以在命令模式中,undo、redo功能可以配合备忘录模式来实现。
备忘录模式的构成角色:
1.原发器类(Originator):创建一个备忘录对象,使用备忘录存储它的内部状态。
2.负责人类(CareTaker):负责保存好备忘录对象,不能检查或操作备忘录的内容。
3.备忘录类(Memento):将原发器的内部状态存储起来,原发器根据需要决定备忘录存储原发器的哪些内部状态。防止原发器意外的其他对象访问备忘录。备忘录有两个接口,一个是窄口,一个是宽接口。CareTaker只能看到窄接口,它只能把备忘录传递给其他对象。相反,Oraginator看到的是一个宽接口,允许它访问返回到先前状态所需的数据。
11.观察者模式
观察者模式定义了一个一对多的额依赖关系,让一个或多个观察者对象监察一个主题对象。这样一个主题对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象,使这些观察者对象能够自动更新。
在观察者模式中存在如下几种角色:
(1)抽象主题角色
主题角色把所有的观察者对象的引用保存在一个列表里;每个主题都可以有任何数量的观察者。主题提供一个接口,可以加上或撤消观察者对象;主题角色又称为抽象被观察者(Observable)角色。可以用一个抽象类或者一个接口来实现;在具体情况下也不排除使用具体类实现。
(2)抽象观察者(Observer)角色
为所有的具体观察者定义一个接口,在得到通知时更新自己。抽象观察者角色可以用一个抽象类或者一个接口来实现;在具体的情况下也不排除使用具体类来实现。
(3)具体主题(ConcreteSubject)角色
具体主题保存对具体观察者对象有用的内部状态,在这种内部状态改变时,给其观察者发出一个通知,具体主题角色又称为具体被观察者角色。
(4)具体观察者(ConcreteObserver)角色
具体观察者角色用于保存一个指向具体主题对象的引用,和一个与主题的状态相符的状态。具体观察者角色实现抽象观察者角色所要求的更新自己的接口,以便使本身的状态与主题的状态自恰。
12.状态模式
状态模式又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式。状态模式允许一个对象再其内部状态改变的时候改变其行为。 状态模式允许一个对象在其状态改变时,改变它的行为。看起来似乎修改了它的类。
在状态模式中,主要涉及了如下几个角色:
1.环境角色(Context)也称上下文:定义客户端所感兴趣的接口,并且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。
2.抽象状态(State)角色:定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为。
3.具体状态(ConcreteState)角色:每一个具体状态类都实现了环境(Context)的一个状态所对应的行为。