2018-04-29 行为型模式
1、责任链模式:目的是避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。先举个见得多的例子,就是iOS中的事件链和响应链。最内层view接收到事件,若不能处理,就传递给其parentview,如果一直不能处理,最终会传递给window然后被丢弃。实现流程还是有点复杂,这个例子比较好:
(1)编辑各个接收者的统一接口父类,包括消息处理接口,和设置下一个接收者的接口
(2)编辑各个接收者类
(3)编辑责任链类,主要是初始化各个接收者类,并配置好它们在链中的顺序
(4)在实际应用场景,把需要处理的信息交给责任链类即可。
很显然,这样处理有很多好处。
(1)发送者和接收者解耦
(2)简化了实际场景中的接口调用,基本没有了if else等。
(3)显然责任链类是很容易根据需求改变顺序或增加节点的,改动实在多,直接多写一个责任链类,可扩展性是相当的好
使用场景:同一信息有多个类可以处理,具体哪个类,要在运行时决定。
2、命令模式:从描述上看,与外观模式非常相似,它们都是在调用者与实际执行者之间添加了一层抽象,简化了上层调用,增加了可扩展性。区别在于,外观模式在实现时,只是提供了操作接口,而命令模式实际上为每个命令设计了一个‘命令类’,这样做的优势就是,方便对行为进行记录、撤销等操作。比如在‘女神快跑’游戏中,如果我们只想实现对角色进行移动、使用道具等操作,使用外观模式或者不使用设计模式都是可以实现的。但若我们想实现对游戏的回放,则需要对游戏中的每次操作进行记录,这时就可以使用命令模式,每次操作后都可以对‘操作对象’进行记录。命令模式的实现流程:
(1)一个抽象命令类,定义命令执行接口
(2)各个命令实现类,主要就是构造方法和实现命令执行接口
(3)一个统一的命令调用类,将所有命令调用放到这里面,做一层抽象,顺便在每次命令执行后做记录
(4)最上层调用中,只使用命令调用类来发送命令,具体的命令类对上层不可见。
3、中介者模式:当多个类之间相互耦合,形成网状结构时,会导致系统复杂难懂。这时我们加入一个中介者,将其变为一个星形结构,就可以降低系统复杂度,但中介者类很容易变得庞大。iOS中应用了大量中介者模式,这里就不多说了。
4、备忘录模式,很好理解。每次对数据进行操作前,都将其复制一份存在备忘录中,使得用户有吃后悔药的机会。至于实现方面,不想多说,
5、观察者模式:用得太多了,不想多说。
6、状态模式:在‘植物大战海盗’中的卡牌类中,卡牌会根据其状态作出不同显示。这中情景可总结为‘类的行为是基于它的状态改变的’。项目中只有选中和未选中状态,所以一个if判断就解决问题了。但若这里的状态有十几种,后面的还可能不断的增加和改变,不同的开发者都可能添加卡牌的状态,行为代码还非常的长。那么可以想想,这里的if else会非常的长,这个类到后面也会很大,多人同时添加状态时都会来改这一份代码。这种情况下,就很适合使用状态模式了。在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。这个例子非常典型:
(1)抽象状态类,定义行为接口doAction
(2)对每个状态定义一种状态实现类,根据状态实现其行为接口
(3)定义context类,用于存储当前状态对应的状态类,当然也需要定义一个状态枚举
(4)在最上层调用,初始化状态类,然后将context传入doAction执行动作。在doAction内部,执行完所需动作后,会设置context的状态。扩展时做两件事,一个是新写状态类,二是添加对应的枚举值。
Context context = new Context();
StartState startState = new StartState();
startState.doAction(context);
7、策略模式:初看与状态模式非常相似,代码结构也非常相近。这里就直接从最上层应用需求入手:
(1)抽象策略类
(2)对每个策略定义一种策略实现类,根据状态实现其行为接口
(3)定义context类,用于存储当前应用的策略,公开doAction接口,内部调用其策略类的行为接口
(4)最上层调用,只需在需要是设置context的策略对象和调用doAction,非常简单。扩展的时候只需要添加策略类,并在最上层直接用,不需要修改context类,也没有一长串的if else,连状态枚举也没有,可维护性很好。
Context context = new Context(new OperationAdd());
context.doAction(10,5);
从上面的例子可以看出,策略模式与状态模式,都是为了把干什么和怎么干分开,结构非常相近。最本质的区别,就从使用场景中所需传入的参数上寻找。状态模式在执行动作是,基本不需要其它参数了,而策略模式一般都要传入其它参数。就这么总结把:
(1)状态模式重在根据自身的不同状态来决定自身的行为和表现,一般不需要传入其它参数,因为被动作的对象是自己
(2)策略模式重在使用不同的策略来改变别人,一般都要传入其它参数,因为被动作的对象是其它对象。
8、模版模式,可以说是最简单的一种设计模式,不想多说。与外观模式的区别是,外观模式是直接隐藏了子接口,而模版模式公开了子接口,单纯的只是把具体实现延迟到子类中。可用的环境:多个类有统一的接口结构时,比如玩所有的游戏都是打开游戏、玩游戏、关闭游戏这几个基本步骤。
9、访问者模式:解决稳定的数据结构和易变的操作耦合问题,使用场景:
(1)对象结构比较稳定,但经常需要在此对象结构上定义新的操作。
(2)需要对一个对象结构中的对象进行很多不同的且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。
比如一个女人的不同部位被不同的人触碰时,会有不同的反应。
实现方面,这个例子很不错:
(1)一个稳定的数据结构,对其被访问的每个部分,定义一个accept接口,传入Visitor类,执行Visitor的visit方法
(2)根据需求,定义不同的visitor类,它们要针对被访问者的不同部分,实现一个visit方法
(3)最上层调用:
ComputerPart computer = new Computer();
computer.accept(new ComputerPartDisplayVisitor());