设计模式
设计模式
创建型模式
Factory 工厂
Abstract Factory 抽象工厂 Kit
产品族 产品层级

由具体工厂生产品牌1的产品,品牌1的产品族由A类产品1和B类产品1组合而成
使用处:
- 系统独立于产品的创建以及组合和表示
- 系统需要由多个产品系列中的一个来配置
- 强调产品对象的设计和联合使用
- 产品类库,只展现接口而不是实现
优点:
- 隔离具体的类,只给客户提供产生产品族的方法
- 易于改变整个产品系列,只需改工厂生成实例的部分
- 有利于产品的一致性,工厂让产品线上都是一个品牌的
缺点
难以支持新品种的产品,要支持新品种的产品,就要改AbstractFactory类和它的所有子类(+createProductC())
->给创建对象的操作添加参数create(Product sth)
Simple Factory简单工厂
Factory Method工厂方法
留下一个创建对象的接口,让子类决定实例化。
ConcreteCreator::factoryMethod(){
return ConcreteCreator()
}
Creator::anOperation(){
product=factoryMethod()
}

使用处:
- 该类要创建一个对象,但是不知道这个对象的类
- 该类希望由子类来指定它创建的对象
- 该类将创建对象的职责给某个子类,而且可以选择是哪个子类
优点:
- 为子类提供一个挂钩hook的地方,可以用于拓展
缺点:
- 客户为了创建特定的ConcreteProduct就不得不创建Creator的子类
参数化工厂方法->可以创建多种产品
Builder 建造者 生成器
Prototype 原型
Singleton 单例 需要看PPT!!!
Singleton Singleton::getInstance(){
if(uniqueInstance==0)
uniqueInstance=Singleton()
return uniqueInstance
}

让类自身保持它自己的唯一实例(唯一访问该实例的方法、屏蔽构建方法)
使用处:
- 类只能有一个实例
- 唯一实例可以通过子类化拓展,且客户无需更改代码就可以用到这个拓展:返回单例的时候根据条件返回单例的某个子类的实例
优点:
- 唯一实例可以受控访问
- 缩小名空间(相比于全局变量)
- 允许对操作和表示的精细化,Singleton可以由子类来进行拓展
- 允许可变数目的实例
- 比类操作更加灵活,类操作不能允许一个类有多个实例等等
问题:
- 不能保证静态对象只有一个实例被声明
- 可能没有足够的信息进行静态初始化
- C++的单件之间不存在依赖关系
结构型模式
Adapter 适配器 (class object)
类适配器
Adapter::request(){
specificRequest()
}

对象适配器
Adapter::request(){
adaptee->specificRequest()
}

Adaptee:需要进行适配的类,提供的现成的内容
Target:目标接口
Adapter:进行适配的类,将Adaptee调整到与Target接口一致
使用处
- 需要使用已经存在的类,但是接口不符合要求
- 需要创建可以复用的类,这个类可以与其他不相关、不可预见、不兼容的类协作
- 需要使用已经存在的子类,对象适配器可以适配它的父类接口
优点:
- 类适配器
- 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和ConcreteComponent同属父类Component,Decorator用于包装ConcreteComponent,为它提供相应状态和功能。调用时最外层Operation->包装的里层 层层递归调用。
使用处:
- 不影响其他对象,动态、透明给单个对象添加职责
- 处理可以撤销的职责
- 不能采用生成子类的方式进行扩充:比如有大量独立的拓展,子类数目爆炸
优点:
- 比静态继承更加灵活,能够进行方法属性的组合和匹配,可以容易地重复添加一个特性
- 避免在层次结构高层的类有太多特征,使用简单的类为组件逐级特征
缺点:
- Decorator和Component的对象标识相同,但实际上Decorator只是透明的保证
- 有许多小对象,易于定制,但是难于学习和排错
Facade 外观
Flyweight 享元
Proxy 代理
Proxy::request(){
realSubject->request()
}

客户使用Proxy,而不是直接使用RealSubject。在Proxy中先返回一个框架,等待加载结束后才返回RealSubject。
使用处:
- 远程代理 Remote Proxy:为一个对象在不同的地址空间提供局部代理(Ambassador 大使)
- 虚代理 Virtual Proxy:当需要创建开销很大的对象
- 保护代理 Protection Proxy:控制对原始对象的访问
- 智能指针 Smart Reference:在访问对象的时候附加操作:引用计数,第一次引用装入内存,加锁
优点:
- 引入了一定程度的间接性:隐藏对象存在于不同地址空间的事实;最优化;附加内务处理
- 延迟大对象的拷贝过程,只有在修改的时候才真正拷贝它(否则引用计数),降低拷贝开销。
行为模式
Chain Of Responsibility 责任链
Command 命令
Interpreter 解释器 (class)

为特定代码构建解释器。首先构建抽象语法树,NonterminalExpression非终结符表达式(文法规则),Terminal终结符表达式(词法规则?)
优点:
- 易于改变和拓展文法,利用类和继承表示文法
- 易于实现文法
- 可以在类上增加操作用于解释表达式
缺点:
- 复杂的文法难以维护
创建抽象语法树
定义解释操作
共享终结符:享元模式
Iterator 迭代器
Mediator 中介者
Memento 备忘录
Observer 观察者模式 Publish-subscribe 发布订阅 Dependents 依赖
Subject::notify(){
for observer:observers{
observer->update()
}
}
ConcreteObserver::update(){
observerState=subject->getState()
}

对象间,多个对象依赖于一个对象(各个ConcreteObserver依赖于Subject),当它改变时,多个对象都得到通知并自动更新。
使用处:
- 抽象模型两个方面,一个方面依赖于另一个,将其分别封装
- 一个对象的改变需要同时改变其他对象,而不知道具体多少对象有待改变
- 一个对象必须通知其他对象,而不能假定它是谁
优点:
- 目标和观察者之间不是紧密耦合的
- 支持广播通信,发送通知不需要指定接收者
缺点:
- 在目标上一个无害的操作可能会引发一系列意外的更新,而且这些更新通常不说明改变了什么
引发更新:由目标设定(导致多次更新) 由客户设定(给客户增加了触发更新的责任)

State 状态
Strategy策略 Policy

Context维护一个策略引用,这个引用可以改变为ConcreteStrategyA、B、C等具体策略引用,在调用时向策略传入必要的数据进行调用。
使用处:
- 多种行为
- 算法变体
优点:
- 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)
}

首先定义了Element树,每个节点提供了Accept方法。定义Visitor,下辖经过每个Element节点的动作。这样可以让一个Visitor进行遍历的时候执行对应动作。
使用处:
- 操作对象的结构很少改变,但是经常需要定义新的动作。
- 操作对象要进行的动作有多个,且不相关->把这些操作对象中的相关动作集中到Visitor里
- 操作对象各个的接口不同,需要实施依赖于具体类的动作

优点:
- 易于增加新的动作->增加新的访问者
- 访问者集中相关的操作,分离无关的操作
- 访问者通过类的层次进行访问,不需要保证访问的对象有相同类型
缺点:
- 增加新的ConcreteElement困难,需要修改每个访问者
- 可能在访问么对象结构的时候累计状态
- 破坏封装,需要对访问者提供访问元素内部状态的公共操作
双分派:执行的操作取决于Visitor类型和Element类型
遍历节点:对象结构中、使用迭代器、访问者中
补充
Reactor 反应器
+时序图
MVC模式
+时序图