设计模式

XiLaiTL大约 10 分钟

设计模式

创建型模式

Factory 工厂

Abstract Factory 抽象工厂 Kit

产品族 产品层级

FactoryAbstract
FactoryAbstract

由具体工厂生产品牌1的产品,品牌1的产品族由A类产品1和B类产品1组合而成

使用处:

  1. 系统独立于产品的创建以及组合和表示
  2. 系统需要由多个产品系列中的一个来配置
  3. 强调产品对象的设计和联合使用
  4. 产品类库,只展现接口而不是实现

优点:

  • 隔离具体的类,只给客户提供产生产品族的方法
  • 易于改变整个产品系列,只需改工厂生成实例的部分
  • 有利于产品的一致性,工厂让产品线上都是一个品牌的

缺点

  • 难以支持新品种的产品,要支持新品种的产品,就要改AbstractFactory类和它的所有子类(+createProductC())

    ->给创建对象的操作添加参数create(Product sth)

Simple Factory简单工厂

Factory Method工厂方法

留下一个创建对象的接口,让子类决定实例化。

ConcreteCreator::factoryMethod(){
	return ConcreteCreator()
}
Creator::anOperation(){
	product=factoryMethod()
}
FactoryMethod
FactoryMethod

使用处:

  1. 该类要创建一个对象,但是不知道这个对象的类
  2. 该类希望由子类来指定它创建的对象
  3. 该类将创建对象的职责给某个子类,而且可以选择是哪个子类

优点:

  • 为子类提供一个挂钩hook的地方,可以用于拓展

缺点:

  • 客户为了创建特定的ConcreteProduct就不得不创建Creator的子类

参数化工厂方法->可以创建多种产品

Builder 建造者 生成器

Prototype 原型

Singleton 单例 需要看PPT!!!

Singleton Singleton::getInstance(){
	if(uniqueInstance==0)
		uniqueInstance=Singleton()
	return uniqueInstance
}
Singleton
Singleton

让类自身保持它自己的唯一实例(唯一访问该实例的方法、屏蔽构建方法)

使用处:

  1. 类只能有一个实例
  2. 唯一实例可以通过子类化拓展,且客户无需更改代码就可以用到这个拓展:返回单例的时候根据条件返回单例的某个子类的实例

优点:

  • 唯一实例可以受控访问
  • 缩小名空间(相比于全局变量)
  • 允许对操作和表示的精细化,Singleton可以由子类来进行拓展
  • 允许可变数目的实例
  • 比类操作更加灵活,类操作不能允许一个类有多个实例等等

问题:

  • 不能保证静态对象只有一个实例被声明
  • 可能没有足够的信息进行静态初始化
  • C++的单件之间不存在依赖关系

结构型模式

Adapter 适配器 (class object)

类适配器

Adapter::request(){
	specificRequest()
}
AdapterClass
AdapterClass

对象适配器

Adapter::request(){
	adaptee->specificRequest()
}
AdapterObject
AdapterObject

Adaptee:需要进行适配的类,提供的现成的内容

Target:目标接口

Adapter:进行适配的类,将Adaptee调整到与Target接口一致

使用处

  1. 需要使用已经存在的类,但是接口不符合要求
  2. 需要创建可以复用的类,这个类可以与其他不相关、不可预见、不兼容的类协作
  3. 需要使用已经存在的子类,对象适配器可以适配它的父类接口

优点:

  • 类适配器
    • Adapter可以重定义Adaptee的部分行为
    • client仅仅引入了一个对象,不需要额外指针引用到adaptee
  • 对象适配器
    • 允许一个Adapter适配多个Adaptee(Adapee和它的子类),一次性给它们添加功能

缺点:

  • 类适配器

    • 不能满足匹配一个类和它的所有子类的需求
  • 对象适配器

    • 重定义Adaptee的行为比较困难,需要生成Adaptee的子类
  • 潜在工作量取决于Adaptee和Target接口相似度

  • 不对所有的客户透明,被适配的对象不再兼容Adaptee接口->改用双向适配器

Bridge 桥接 Handle Body

Composite 组合

Decorator 装饰器

Decorator::operation(){
	component->Operation()
}

ConcreteDecoratorB::operation(){
	super->operation()
	addedBehavior()
}
Decorator
Decorator

给某个对象而不是类增加功能。

Decorator和ConcreteComponent同属父类Component,Decorator用于包装ConcreteComponent,为它提供相应状态和功能。调用时最外层Operation->包装的里层 层层递归调用。

使用处:

  1. 不影响其他对象,动态、透明给单个对象添加职责
  2. 处理可以撤销的职责
  3. 不能采用生成子类的方式进行扩充:比如有大量独立的拓展,子类数目爆炸

优点:

  • 比静态继承更加灵活,能够进行方法属性的组合和匹配,可以容易地重复添加一个特性
  • 避免在层次结构高层的类有太多特征,使用简单的类为组件逐级特征

缺点:

  • Decorator和Component的对象标识相同,但实际上Decorator只是透明的保证
  • 有许多小对象,易于定制,但是难于学习和排错

Facade 外观

Flyweight 享元

Proxy 代理

Proxy::request(){
	realSubject->request()
}
Proxy
Proxy

客户使用Proxy,而不是直接使用RealSubject。在Proxy中先返回一个框架,等待加载结束后才返回RealSubject。

使用处:

  1. 远程代理 Remote Proxy:为一个对象在不同的地址空间提供局部代理(Ambassador 大使)
  2. 虚代理 Virtual Proxy:当需要创建开销很大的对象
  3. 保护代理 Protection Proxy:控制对原始对象的访问
  4. 智能指针 Smart Reference:在访问对象的时候附加操作:引用计数,第一次引用装入内存,加锁

优点:

  • 引入了一定程度的间接性:隐藏对象存在于不同地址空间的事实;最优化;附加内务处理
  • 延迟大对象的拷贝过程,只有在修改的时候才真正拷贝它(否则引用计数),降低拷贝开销。

行为模式

Chain Of Responsibility 责任链

Command 命令

Interpreter 解释器 (class)

Interpreter
Interpreter

为特定代码构建解释器。首先构建抽象语法树,NonterminalExpression非终结符表达式(文法规则),Terminal终结符表达式(词法规则?)

优点:

  • 易于改变和拓展文法,利用类和继承表示文法
  • 易于实现文法
  • 可以在类上增加操作用于解释表达式

缺点:

  • 复杂的文法难以维护

创建抽象语法树

定义解释操作

共享终结符:享元模式

Iterator 迭代器

Mediator 中介者

Memento 备忘录

Observer 观察者模式 Publish-subscribe 发布订阅 Dependents 依赖

Subject::notify(){
	for observer:observers{
		observer->update()
	}
}

ConcreteObserver::update(){
	observerState=subject->getState()
}
Observer
Observer

对象间,多个对象依赖于一个对象(各个ConcreteObserver依赖于Subject),当它改变时,多个对象都得到通知并自动更新。

使用处:

  1. 抽象模型两个方面,一个方面依赖于另一个,将其分别封装
  2. 一个对象的改变需要同时改变其他对象,而不知道具体多少对象有待改变
  3. 一个对象必须通知其他对象,而不能假定它是谁

优点:

  • 目标和观察者之间不是紧密耦合的
  • 支持广播通信,发送通知不需要指定接收者

缺点:

  • 在目标上一个无害的操作可能会引发一系列意外的更新,而且这些更新通常不说明改变了什么

引发更新:由目标设定(导致多次更新) 由客户设定(给客户增加了触发更新的责任)

ObserverSequence
ObserverSequence

State 状态

Strategy策略 Policy

Strategy
Strategy

Context维护一个策略引用,这个引用可以改变为ConcreteStrategyA、B、C等具体策略引用,在调用时向策略传入必要的数据进行调用。

使用处:

  1. 多种行为
  2. 算法变体

优点:

  • Strategy类通过继承关系,析出了可重用的部分
  • 使得可以独立于Context去改变算法,易于理解易于扩展易于维护。如果是通过Context子类继承重写方法实现支持多种策略的方式,这样会导致算法的实现和Context子类的实现混合在一起。
  • 消除了一些条件语句。
  • 客户可以根据要求选择不同的策略

缺点:

  • 客户必须了解不同的策略,可能不得不向客户暴露具体的实现
  • Strategy和Context的通信开销,Context不得不提供所有Strategy需要的信息的并集,而有些Strategy用不到这些关系,然而处理这个问题的方式是Context和Strategy更加耦合。
  • 增加了对象的数目。(解决方式:享元)

Template Method 模版方法 (class)

Visitor 访问者

ConcreteElementA::accept(v:Visitor){
	v->visitorConcreteElementA(this)
}
ConcreteElementB::accept(v:Visitor){
	v->visitorConcreteElementB(this)
}
Visitor
Visitor

首先定义了Element树,每个节点提供了Accept方法。定义Visitor,下辖经过每个Element节点的动作。这样可以让一个Visitor进行遍历的时候执行对应动作。

使用处:

  1. 操作对象的结构很少改变,但是经常需要定义新的动作。
  2. 操作对象要进行的动作有多个,且不相关->把这些操作对象中的相关动作集中到Visitor里
  3. 操作对象各个的接口不同,需要实施依赖于具体类的动作
VisitorSequence
VisitorSequence

优点:

  • 易于增加新的动作->增加新的访问者
  • 访问者集中相关的操作,分离无关的操作
  • 访问者通过类的层次进行访问,不需要保证访问的对象有相同类型

缺点:

  • 增加新的ConcreteElement困难,需要修改每个访问者
  • 可能在访问么对象结构的时候累计状态
  • 破坏封装,需要对访问者提供访问元素内部状态的公共操作

双分派:执行的操作取决于Visitor类型和Element类型

遍历节点:对象结构中、使用迭代器、访问者中

补充

Reactor 反应器

+时序图

MVC模式

+时序图

软件体系结构

分层的风格

管道过滤器风格

主程序子程序风格

面向对象风格

基于共享数据的事件风格

上次编辑于:
贡献者: XiLaiTL