本篇是四部曲的第三篇,第一篇请点这里iOS设计模式四部曲(一):创建型模式,第二篇请点击这里iOS设计模式四部曲(二):结构型模式。由于个人能力有限,文中难免有一些遗漏或者错误,请各位看官不吝赐教!谢谢!本文所有Demo可以在我的Git上获取,请点击这里
上图是整个设计模式的目录,这篇文章是其中的第三部分:行为型模式。行为型模式包括:责任链模式(Chain of Responsibility)
,命令模式(Command)
,中介者模式(Mediator)
,观察者模式(Observer)
,备忘录模式(Memento)
,策略模式(Strategy)
,访问者模式(Visitor)
,模板方法模式(TemplateMethod)
,状态模式(State)
,迭代器模式(Iterator)
,解释器模式(Interpreter)
。下面我们就开始吧~
责任链模式(Chain of Responsibility):
1.定义: 责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之前的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,知道有对象处理它为止。
2. 使用场景: 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时确定。
3. 具体实现: 这里举了一个实际中公司请假批假的例子,具体请点击这里查看
4.优点: 1.低耦合:将请求和处理分开,请求者可以不用知道是谁处理的。2.新增和修改新的处理类比较容易
5.缺点: 每个请求都是从链头遍历到链尾,如果链比较长会产生一定的性能问题,调试起来也比较麻烦。
6.注意事项: 避免超长链的情况出现
命令模式(Command):
1.定义: 命令模式将请求封装成对象,从而可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销和恢复的操作。
2. 使用场景: 在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理的时候。
3. 具体实现: YTKNetwork就是用的命令模式,推荐大家学习。这里我举了一个吃饭点菜的例子,具体请点击这里查看
4.优点: 1.类间解耦:调用者与接收者之间没有任何依赖关系。2.扩展性良好:新的命令可以很容易添加到系统中去。
5.缺点: 使用命令模式可能会导致系统有过多的具体命令类。
中介者模式(Mediator):
1.定义: 中介者模式就是用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
2. 使用场景: 多个类相互依赖,形成了网状结构的时候可以考虑使用中介者模式。
3. 具体实现: 这里举了一个聊天室的例子,具体请点击这里查看
4.优点: 1.解耦:通过中介者模式,我们可以将复杂关系的网状结构变成结构简单的以中介者为核心的星形结构,每个对象不再和它与之关联的对象直接发生相互作用,而是通过中介者对象来另一个对象发生相互作用。2.降低了类的复杂度,将一对多转化成了一对一。
5.缺点:中介者模式在某些情况会膨胀得很大,而且逻辑复杂,中介类越多越复杂,越难以维护。
6.注意事项: 类之间的依赖关系是必然存在的,所以不一定有多个依赖关系的时候就考虑使用中介者模式。中介者模式适用于多个对象之间的紧密耦合的情况,紧密耦合的定义标准是:在类图中出现了蜘蛛网状结构,这种情况就要考虑使用中介者模式,中介者模式可以把蜘蛛网梳理成星型结构,使原本复杂混乱的关系变得清晰简单。
观察者模式(Observer):
1.定义: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
2. 使用场景: 一个对象的状态发生改变,所有的依赖对象都将得到通知的时候。
3. 具体实现: Objective-C中的通知以及KVO都是观察者模式的具体实现。这里举了一个找工作订阅的例子,具体请点击这里查看
4.优点: 1.观察者和被观察者是抽象耦合的,扩展比较方便。2.建立一套触发机制。
5.缺点: 1.如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2.如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3.观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
备忘录模式(Memento):
1.定义: 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就开奖对象恢复到原先保存的状态了。
2. 使用场景: 需要存档的时候,比如说游戏中的存档。
3. 具体实现: 打游戏时的存档,数据库的事务管理,SVN以及Git代码的版本控制系统等等都可以说成是备忘录模式的实例。这里我简单的举了一下例子,具体请点击这里查看
4.优点: 1.给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。 2.实现了信息的封装,使得用户不需要关心状态的保存细节。
5.缺点: 在一些场景下比较消耗资源。
6.注意事项: 不要在频繁建立备份的场景中使用备忘录模式,比如说在for循环中。
策略模式(Strategy):
1.定义: 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。
2. 使用场景: 1.多个类只有在算法或行为上稍有不同的场景。2.算法需要自由切换的场景。3.需要屏蔽算法规则的场景。
3. 具体实现: 具体请点击这里查看
4.优点: 1.算法可以自由切换。 2.避免使用多重条件判断。 3.扩展性良好。
5.缺点:1.策略类会增多。 2.所有策略类都需要对外暴露。
6.注意事项: 如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
访问者模式(Visitor):
1.定义: 访问者模式封装了一些作用于某种数据结构中的各元素操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
2. 使用场景: 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。
3. 具体实现: 这里举了一个悲观的人和乐观的人对待不同事物的反应的实例,具体请点击这里查看,如果想增加Action就比较方便,但是如果想增加一个既悲观又乐观的人就有一点麻烦了。
4.优点: 1.符合单一职责原则。 2.优秀的扩展性。 3.灵活性高
5.缺点:1.具体元素对访问者公布细节,违反了迪米特原则。 2.具体元素变更比较困难。 3.违反了依赖倒置原则,依赖了具体类,没有依赖抽象。
模板方法模式(TemplateMethod):
1.定义: 定义一个操作中的算法的框架,而降一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
2. 使用场景: 1.多个子类有公有的方法,并且逻辑基本相同时。2.有重要、复杂的算法的时候,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
3. 具体实现: 这里简单举了一个Android 和iOS项目的从code到发布的简易过程Demo,具体请点击这里查看
4.优点: 1.封装不变部分,扩展可变部分。 2.提取公共代码,便于维护。 3.行为由父类控制,子类实现。
5.缺点: 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
状态模式(State):
1.定义: 当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
2. 使用场景: 1.行为随状态改变而改变的场景。2.条件、分支判断语句的替代者。
3. 具体实现: 这里举了一个不太恰当的例子,假如一支笔有3种状态可以切换,可以写钢笔字,圆珠笔字,毛笔字,具体请点击这里查看。再举一个实际中典型的例子就是酒店管理房间的时候,房间应该会有三种状态:空闲,已预订,已入住,同理。
4.优点: 1.结构清晰,避免了过多的选择判断语句。2.封装性比较好。
5.缺点: 子类会比较多,增加了复杂度。
迭代器模式(Iterator):
1.定义: 迭代器模式提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。
2. 使用场景: 一个聚合对象有遍历的需求
3. 具体实现: 在 Cocoa Touch 中的 NSEnumerator类
就实现了迭代器模式。还有基于块的枚举
也是迭代器模式的实现等等
4.优点: 1.它支持以不同的方式遍历一个聚合对象。2.增加新的collection类和迭代器类都很方便。
5.缺点: 迭代器和collection类是对应的,增加新的collection类就会增加新的迭代器,类的个数成对增加,可能会增加系统复杂度。
解释器模式(Interpreter):
1.定义: 给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
2. 使用场景: 解释器模式在实际项目中用到的比较少,正则表达式就是用的解释器模式。
3. 具体实现: 正则表达式。
4.优点: 容易改变和扩展问法。
5.缺点: 效率是严重的问题。
扩展阅读:
iOS 中的 21 种设计模式
https://github.com/kamranahmedse/design-patterns-for-humans
EOF:这篇文章通过Demo梳理了设计模式中的行为型模式,由于个人能力有限,难免有一些遗漏或者错误,还请各位看官不吝赐教! 本文已同步到个人博客,欢迎关注,欢迎点赞,欢迎star,欢迎一起交流,一起进步!🤓