《设计模式》学习笔记

《设计模式》学习笔记

参考教材:《设计模式——可复用面向对象软件的基础》

1. 创建型模式

创建型模式旨在对一系列类的实例化工作进行封装与抽象。简而言之,如果我们的程序主体逻辑中经常出现形如 SomeClass* pSomeClass = new SomeClass; 这样的语句,几乎可以认为我们的程序不具有良好可复用性。比如当我们想要将全文中所有的 new SomeClass 都换成 new AnotherClass,就不得不使用 IDE 的替换功能,而如果我们能够定义一个类 FactoryClass 用于生成所有的对象,我们就可以使用 AbstrctClass* p = GetFactoryClassObject()->CreateSomeClass() 的方式生成一个 SomeClass 的对象,我们可以对 FactoryClass 进行派生以实现 “风格替换” 的功能。

1.1 Abstract Factory——抽象工厂

定义一个 “对象创建器类” (AbsractFactoryClass),每当我们想要创建一个对象,就先找到一个 AbsractFactoryClass 子类的实例,再调用他的成员函数来实现创建对象的功能。当我们需要整体改变程序中的“风格时”,对 AbsractFactoryClass 进行派生。简而言之,抽象工厂就是对某些类的实例化进行抽象。当我们想要在一个函数中实例化某个对象时,我们可以对这个函数传入一个 Absract Factory 类的引用以指导我们实例化哪个类。

1.2 Builder——建构器

对某个类的构造函数进行抽象,比如某个对象内部有着复杂的结构,需要比较复杂的初始化过程,有时可能需要选择不同的算法对对象进行初始化。这时我们可以考虑把算法封装到建构器 Builder 中,在这个类的构造函数中传入一个建构器的引用以实现对算法的选择。可以对构造器基类进行派生以实现不同的构造算法。

1.3 Factory Method——工厂方法

某个抽象类的实例化过程进行抽象。由于抽象类在实例化时并不知道要实例化哪个子类,如果硬编码地写入一个子类的实例化会影响代码的可复用性。另一个角度讲,利用工厂方法,我们还可以在对象实例化的同时做一些额外的初始化工作,比如我们可以为当前构造的对象提供一个“钩子”以拓展该对象的功能。

1.4 Prototype——原型

在类中定义一个叫做 clone() 的虚函数,他的功能是(深)拷贝一个当前对象从而得到一个新的对象,这个被拷贝的对象叫做”原型“。在某些情况下 Prototype 可以用来减少类的数量。

1.5 Singleton——单例

将某个类的构造函数定义成私有的,保证这个类至多只有一个对象,然后提供一个共有的类方法/静态方法来获取这个对象。

2. 结构型模式

2.1 Adapter——适配器

我们有一个抽象类 IClass 描述了一系列通用的结构,但是现在有一个先前已经实现了的类 ClassA,他并不是这个抽象类的子类,换言之具有不同的接口。可以考虑定义一个适配器类,它继承自抽象类 IClass,组合/聚合一个 ClassA 对象以实现接口的适配。

还可以使用多重继承来实现双向适配。例如我们已经有两个抽象类 IClassAIClassB 但是他们接口不同,我们可以派生一个这两个类的公共子类,从而实现双向适配。双向适配的好处是能够让使用者(或者客户)完全意识不到我们使用的对象的原生接口到底是符合 IClassA 的接口集合还是符合 IClassB 的接口集合。

2.2 Bridge——桥接

将类的抽象与类的实现分离。SomeClass 是某个抽象类,这个抽象类中组合了一个 SomeClassImpSomeClassImp 也是一个抽象类,称为 SomeClass 的 ”实现类“,实现类的接口中定义了一些基础的方法,被实现类中要调用实现类中的方法去实现一些复杂的组合功能。这样做的好处是,保障了 SomeClass 的子类一定都由 SomeClassImp 的子类”实现“。当一个程序跨平台运行时,只需要对 SomeClassImp 类进行派生。

在派生的过程中可能会出现 SomeClassASomeClassImpA 实现,SomeClassBSomeClassImpB 实现的情况,这种情况可以使用 Abstract Factory 来实现关联性的配置。

2.3 Composite——组合

在子类对象中添加若干个基类的指针以实现一种树形的结构。比如说(可显示)图形类 Graphics 是一个抽象类,它有若干个子类如:文本内容 Text,图片类 Picture 以及容器类 Container。组合图形类对象中含有一个图形类对象的指针数组,使得其成为整个树形结点中的非叶子节点,而 TextPicture 则是树形结构中的叶子节点。

Composite 模式是一种适用领域颇为广泛的设计模式。

2.4 Decorator——装饰

在子类对象中添加一个基类的指针以实现对基类其他子类功能的拓展。假设 Component 是所有组件的公共基类,TextAreaComponent 的子类。起初 TextArea 没有卷滚条,我们从 Component 中派生一个子类 ScrollDecorator 用于为被修饰对象增加卷滚条的显示。这样的处理方式比直接多重继承更加灵活。

Decorator 有的时候很像后面说到的 Strategy, Decorator 主要用于外观上的修饰, Strategy 主要用于算法上的修饰。

2.5 Facade——外观

当要完成某一复杂任务时,我们将问题划分为很多子问题,然后定义了若干个类以解决这些问题。这些类之间可能具有十分复杂的关系,这个时候可以定义一个 Facade 外观类来将整个子系统的功能进行封装。在没有 Facade 类之前,客户使用子系统可能是通过子系统中的某些具体的子系统使用该系统,这不利于软件的复用。此时应该对接口进行统一的抽象而客户只能使用 Facade 间接调用各个子系统的功能,可以降低客户和子系统的耦合度。

2.6 Flyweight——享元

使用共享池技术支持大量细粒度的对象。Flyweight 不存储和应用场景相关的数据而只存放 “内部状态”,这使得 Flyweight 对象可以被很多其他对象所共享。例如当我们想要把一些字母以点阵的形式输出时,我们没必要为每个字母 ‘a’ 对象都建立一个字形码,而可以将 ‘a’ 的字形码存储与一个共享池中,程序在有必要时可以引用这个共享池中的字形码对象。

我们经常要使用一个 Flyweight Factory 来管理一个 Flyweight Pool。

2.7 Proxy——代理

有些对象的构造非常耗时,只有当我们确实需要这个对象的时候才去构造这些对象。例如当我们用Word文档打开一个文件时,我们没必要在打开时就立刻把所有图片加载到内存,但是一个图片对象的构造函数必然要把图片完整的从图片文件中将数据读入。我们可以使用图像代理对象代理一个具体的图像对象,图像代理对象中存储一个指向图像对象的指针,起初这个指针是一个空指针。当我们调用图像代理对象的绘制方法时,图像代理对象会检查自己的指针是否为空,如果为空会对这个对象进行构造,从而实现对象的延迟构造。

3. 行为型模式

3.1 Chain of Responsibility——职责链

将处理某一消息的方式封装在一些对象的成员函数中,将这些对象用指针串成一条链。当某个对象的处理函数被调用时,他会检查自己是否有能力处理这个消息,如果有能力则处理,如果没有能力调用他的后继对象的处理函数。职责链能够降低消息发送者和消息接收者的耦合度,消息发送者并不知道自己发出的消息具体被哪个算法接收并处理。

3.2 Command——命令

SomeClass 能够 “触发” 某些动作,但是这个类本身不具有执行这个动作所需的全部信息。这个时候我们可以定义一个 Command 类,SomeClass 聚合一个 Command 类对象,当触发这个动作的时候调用 Command 类的 Execute 方法。例如在一个 IDE 中,我们可能可以点击一个按钮来实现对代码的格式化整理。这个按钮本身并没有文本编辑器中文本框对象的引用,但是他聚合了一个 Command 对象,这个对象能够访问相应的文本框对象。

Command 模式还可以用来实现回调函数。有些时候我们需要派生一个新的线程去完成某些等待或者计算性的任务,当这个任务完成时,我们需要该线程通知主线程,但是该线程可能并不能直接访问主线程中的某些对象。可以考虑在启动线程时,主线程向子线程传递一个 Command 对象作为参数,而这个 Command 对象能够将对应的消息发送给主线程。

结合使用 Command 模式 和 Composite 模式能够实现一种面向对象的脚本编程框架。

3.3 Interpreter——解释器

定义一种简单的语言,解释器负责将该语言从字符串形式翻译为抽象语法树的形式。具体的做法是让抽象类 Expression 包含一个 Interpret 方法,自然他的所有子类也包含这个方法。

  • 弃坑跑路 …
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值