chaoz的杂货铺

生命有息、学无止境、折腾不止

0%

设计模式学习计划

计划:

每天 19:00 - 20:00 时间段内花费 30 min - 40 min 学习一个设计模式。

一个月完成。

学习内容:

gitchat 白话设计模式 28 讲

什么是设计模式

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、无数工程师实践的代码设计经验的总结,它是面向对象思想的高度提炼和模板化,使用设计模式是为了让代码具有更高的可重用性,更好的灵活性和可拓展性,更易被人阅读和理解。

学习设计模式的先行条件

熟悉一门面向对象语言、学会阅读 UML 图

UML 类图关系大全
UML 类图关系(泛化 、继承、实现、依赖、关联、聚合、组合)

监听模式/观察者模式

观察者模式是对象的行为模式,又叫发布 - 订阅(Publish/Subscribe)模式、模型 - 视图(Model/View)模式、源 - 监听器(Source/Listener)模式或从属者(Dependents)模式。当你看这些模式的时候,不要觉得陌生,它们就是观察者模式。

观察者模式一般是一种一对多的关系,可以有任意个(一个或多个)观察者对象同时监听某一个对象。监听的对象叫观察者(后面提到监听者,其实就指观察者,两者是等价的),被监听的对象叫被观察者(Observable,也叫主题 Subject)。被观察者对象在状态或内容发生变化时,会通知所有观察者对象,使它们能够做出相应的变化(如自动更新自己的信息)。

模型抽象

思考类图设计

模型说明

设计要点

在设计观察者模式的程序时要注意以下几点:

要明确谁是观察者谁是被观察者,只要明白谁是关注对象,问题也就明白了。一般观察者与被观察者之间是多对一的关系,一个被观察对象可以有多个监听对象 (观察者)。如一个编辑框,有鼠标点击的监听者,也有键盘的监听者,还有内容改变的监听者。

Observable 在发送广播通知的时候,无须指定具体的 Observer,Observer 可以自己决定是否要订阅 Subject 的通知。

被观察者至少需要有三个方法:添加监听者、移除监听者、通知 Observer 的方法;观察者至少要有一个方法:更新方法,更新当前的内容,作出相应的处理。

添加监听者、移除监听者在不同的模型称谓中可能会有不同命名,如观察者模型中一般,addObserver,removeObserver;在源 - 监听器(Source/Listener)模型中一般是 attach/detach,应用在桌面编程的窗口中,还可能是 attachWindow/detachWindow,或 Register/UnRegister。不要被名称迷糊了,不管他们是什么名称,其实功能都是一样的,就是添加 / 删除观察者。

推模型和拉模型

观察者模式根据其侧重的功能还可以分为推模型和拉模型。

推模型:

被观察者对象向观察者推送主题的详细信息,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据。一般这种模型的实现中,会把被观察者对象中的全部或部分信息通过 update 的参数传递给观察者 [update (Object obj) ,通过 obj 参数传递]。

拉模型:

被观察者在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到被观察者对象中获取,相当于是观察者从被观察者对象中拉数据。一般这种模型的实现中,会把被观察者对象自身通过 update 方法传递给观察者 [update (Observable observable),通过 observable 参数传递 ],这样在观察者需要获取数据的时候,就可以通过这个引用来获取了。

应用场景

1、对一个对象状态或数据的更新需要其他对象同步更新,或者一个对象的更新需要依赖另一个对象的更新;

2、对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节,如消息推送。

适配器模式

模型抽象

思考类图设计

作用:

接口转换,将原有的接口(或方法)转换成另一种接口;
用新的接口包装一个已有的类;
匹配一个老的组件到一个新的接口。

设计要点

思考设计类图

适配器模式中主要三个角色,在设计适配器模式时要找到并区分这些角色:

目标(Target): 即你期望的目标接口,要转换成的接口。
源对象(Adaptee): 即要被转换的角色,要把谁转换成目标角色。
适配器(Adapter): 适配器模式的核心角色,负责把源对象转换和包装成目标对象。

模型说明

设计要点

适配器模式中主要三个角色,在设计适配器模式时要找到并区分这些角色:

  • 目标(Target):
    即你期望的目标接口,要转换成的接口。

  • 源对象(Adaptee):
    即要被转换的角色,要把谁转换成目标角色。

  • 适配器(Adapter):
    适配器模式的核心角色,负责把源对象转换和包装成目标对象

优缺点

  • 适配器模式的优点

可以让两个没有关联的类一起运行,起着中间转换的作用。
提高了类的复用。
灵活性好,不会破坏原有的系统。

  • 适配器模式的缺点

如果原有系统没有设计好(如 Target 不是抽象类或接口,而一个实体类),适配器模式将很难实现。
过多地使用适配器,容易使代码结构混乱,如明明看到调用的是 A 接口,内部调用的却是 B 接口的实现。

应用场景

1、系统需要使用现有的类,而这些类的接口不符合现有系统的要求。

2、对已有的系统拓展新功能时,尤其适用于在设计良好的系统框架下增加接入第三方的接口或第三方的 SDK 时。

状态模式

模型抽象

思考代码框架与类图

模型说明

1、在状态模式实现的时候,实现的场景状态有时候会非常复杂。决定状态变化的因素也会非常多,这个时候我们可以把决定状态变化的属性单独抽象成一个类 StateInfo,这样判断状态属性是否符合当前的状态 isMatch 时就可以传入更多的信息。

2、每一种状态应当只有唯一的一个实例。

应用场景

1、一个对象的行为取决于它的状态,并且它在运行时可能经常改变它的状态从而改变它的行为。

2、一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态,且每一个分支的业务逻辑非常复杂时,我们可以使用状态模式来拆分他不同分支逻辑,使程序有更好的可读性可维护性。

单例模式

模型抽象

代码框架

1.重写new和init方法
2.自定义metaclass的方法
3.装饰器的方法

类图

基于框架的实现

应用场景

1、你希望这个类只有一个且只能有一个实例;

2、项目中的一些全局管理类(Manager)可以用单例来实现。

职责模式

模型抽象

代码框架

类图

基于框架的实现

模型说明

设计要点

在设计职责模式的程序时要注意以下几点:

请求者与请求内容:谁要发送请求?发送请求的对象称为请求者。请求的内容通过发送请求时的参数进行传递。

有哪些责任人:责任人是构成责任链的关键要素。请求的流动方向是链条中的线,而责任人则是链条上的结点,线和结点才构成了一条链条。

对责任人进行抽象:真实世界中的责任人会多种多样,纷繁复杂,会有不同的职责和功能;但他们也有一个共同的特征——都可以处理请求。所以需要对责任人进行抽象,使他们具有责任的可传递性。

责任人可自由组合:责任链上的责任人可以根据业务的具体逻辑进行自由的组合和排序。

优缺点

  • 优点:

降低耦合度。它将请求的发送者和接受者解耦。
简化了对象。使得对象不需要知道链的结构。
增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任人。
增加新的处理类很方便。

  • 缺点:

不能保证请求一定被接收。
系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。

应用场景

有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
请求的处理具有明显的一层层传递关系。
请求的处理流程和顺序需要程序运行时动态确定。

喜欢这篇文章?打赏一下作者吧!

欢迎关注我的其它发布渠道