设计模式总结(行为形)

观察者模式

定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式的别名包括发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。


优点:

①观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。

②观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知,

缺点:

①如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。

②如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。

③如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。

④虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

适用场景:

①当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两者封装在独立的对象中以使它们可以各自独立地改变和复用的情况下。从方面的这个词中可以想到,观察者模式肯定在AOP(面向方面编程)中有所体现。

②当对一个对象的改变需要同时改变其他对象,而又不知道具体有多少对象有待改变的情况下。

③当一个对象必须通知其他对象,而又不能假定其他对象是谁的情况下。

模板方法模式

定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。


优点:

①实现了代码复用

②能够灵活应对子步骤的变化,符合开放-封闭原则

缺点:

③因为引入了一个抽象类,如果具体实现过多的话,需要用户或开发人员需要花更多的时间去理清类之间的关系。

适用场景:

①一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。

②各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。这是Opdyke和Johnson所描述过的“重分解以一般化”的一个很好的例子。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。

③控制子类扩展。模板方法只在特定点调用“hook”操作,这样就只允许在这些点进行扩展。

职责链模式

避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。职责链模式是一种对象行为型模式。


优点:

①降低了请求的发送者和接收者之间的耦合。

②把多个条件判定分散到各个处理类中,使得代码更加清晰,责任更加明确。

缺点:

①在找到正确的处理对象之前,所有的条件判定都要执行一遍,当责任链过长时,可能会引起性能的问题

②可能导致某个请求不被处理。

适用场景:

一个系统的审批需要多个对象才能完成处理的情况下,例如请假系统等。

代码中存在多个if-else语句的情况下,此时可以考虑使用责任链模式来对代码进行重构。

命令模式

将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。


优点:

①命令模式使得新的命令很容易被加入到系统里。

②可以设计一个命令队列来实现对请求的Undo和Redo操作。

③可以较容易地将命令写入日志。

④可以把命令对象聚合在一起,合成为合成命令。合成命令式合成模式的应用。

缺点:

①使用命令模式可能会导致系统有过多的具体命令类。这会使得命令模式在这样的系统里变得不实际。

适用场景:

①命令的发送者和命令执行者有不同的生命周期。命令发送了并不是立即执行。

②命令需要进行各种管理逻辑。

③需要支持撤消\重做操作

状态模式

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。


优点:

①将状态判断逻辑每个状态类里面,可以简化判断的逻辑。

②当有新的状态出现时,可以通过添加新的状态类来进行扩展,扩展性好。

缺点是:

①如果状态过多的话,会导致有非常多的状态类,加大了开销。

适用场景:

①当一个对象状态转换的条件表达式过于复杂时可以使用状态者模式。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简单化。

②当一个对象行为取决于它的状态,并且它需要在运行时刻根据状态改变它的行为时,就可以考虑使用状态者模式。

解释器模式

给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。


优点:

①易于实现文法:在解释器模式中,一条语法规则用一个解释器对象来解释执行。对于解释器的实现来讲,功能就变得比较简单。

②易于扩展新的语法。由于解释器采用类来描述语法规则,因此可以通过继承等机制创建相应的解释器对象,在创建抽象语法树的时候使用这个新的解释器对象就可以了。

缺点:

①执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。

②对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。

适用场景:

①当一个语言需要解释执行,并可以将该语言中的句子表示为一个抽象语法树的时候,可以考虑使用解释器模式(如XML文档解释、正则表达式等领域)

②一些重复出现的问题可以用一种简单的语言来进行表达。

③一个语言的文法较为简单.

④当执行效率不是关键和主要关心的问题时可考虑解释器模式

中介者模式

用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式。


优点:

①减少了子类生成,Mediator将原本分布于多个对象间的行为集中在一起。改变这些行为只需生成Mediator的子类即可。这样各个Colleague类可被重用。

②简化各同事类的设计和实现,它将各同事类Colleague解耦,Mediator有利于各Colleague间的松耦合. 你可以独立的改变和复用各Colleague类和Mediator类。

③它简化了对象协议: 用Mediator和各Colleague间的一对多的交互来代替多对多的交互。一对多的关系更易于理解、维护和扩展。

④它对对象如何协作进行了抽象 将中介作为一个独立的概念并将其封装在一个对象中,使你将注意力从对象各自本身的行为转移到它们之间的交互上来。这有助于弄清    楚一个系统中的对象是如何交互的。

⑤它使控制集中化 中介者模式将交互的复杂性变为中介者的复杂性。

缺点:

①因为中介者封装了协议,即在具体中介者类中包含了同事之间的交互细节,可能会导致具体中介者类非常复杂,这可能使得中介者自身成为一个难于维护的庞然大物。

适用场景:

①一组定义良好的对象,现在要进行复杂的相互通信。

②想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。

访问者模式

提供一个作用于某对象结构中的各元素的操作表示,它使我们可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式是一种对象行为型模式。


优点:

①访问者模式使得添加新的操作变得容易。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,添加新的操作会变得很复杂。而使用访问者模式,增加新的操作就意味着添②加一个新的访问者类。因此,使得添加新的操作变得容易。

③访问者模式使得有关的行为操作集中到一个访问者对象中,而不是分散到一个个的元素类中。这点类似与"中介者模式"。

④访问者模式可以访问属于不同的等级结构的成员对象,而迭代只能访问属于同一个等级结构的成员对象。

缺点:

①增加新的元素类变得困难。每增加一个新的元素意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中添加相应的具体操作。

适用场景:

①一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。

②需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。 Visitor使得你可以将相关的操作集中起来定义在一个类中。当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。

③定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

策略模式

定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。策略模式是一种对象行为型模式。


优点:

①策略类之间可以自由切换。由于策略类都实现同一个接口,所以使它们之间可以自由切换。

易于扩展。增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码。

②避免使用多重条件选择语句,充分体现面向对象设计思想。

缺点:

①客户端必须知道所有的策略类,并自行决定使用哪一个策略类。

适用场景:

①一个系统需要动态地在几种算法中选择一种的情况下。那么这些算法可以包装到一个个具体的算法类里面,并为这些具体的算法类提供一个统一的接口。

②如果一个对象有很多的行为,如果不使用合适的模式,这些行为就只好使用多重的if-else语句来实现,此时,可以使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象涉及的概念。

备忘录模式

在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样以后就可以把该对象恢复到原先的状态。


优点:

①如果某个操作错误地破坏了数据的完整性,此时可以使用备忘录模式将数据恢复成原来正确的数据。

②备份的状态数据保存在发起人角色之外,这样发起人就不需要对各个备份的状态进行管理。而是由备忘录角色进行管理,而备忘录角色又是由管理者角色管理,符合单一职责原则。

缺点:

①在实际的系统中,可能需要维护多个备份,需要额外的资源,这样对资源的消耗比较严重。

适用场景:

①如果系统需要提供回滚操作时,使用备忘录模式非常合适。例如文本编辑器的Ctrl+Z撤销操作的实现,数据库中事务操作。

迭代器模式

提供了一种方法顺序访问一个聚合对象(理解为集合对象)中各个元素,而又无需暴露该对象的内部表示。


优点:

①迭代器模式使得访问一个聚合对象的内容而无需暴露它的内部表示,即迭代抽象。

②迭代器模式为遍历不同的集合结构提供了一个统一的接口,从而支持同样的算法在不同的集合结构上进行操作

缺点:

①迭代器模式在遍历的同时更改迭代器所在的集合结构会导致出现异常。所以使用foreach语句只能在对集合进行遍历,不能在遍历的同时更改集合中的元素。

适用场景:

①系统需要访问一个聚合对象的内容而无需暴露它的内部表示。

②系统需要支持对聚合对象的多种遍历。

③系统需要为不同的聚合结构提供一个统一的接口。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 30
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Geek-Banana

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值