设计模式 图例

81 阅读11分钟

一、六大设计原则 SOLIDD

  • 单一责任 s - single
一个类只负责一个功能领域中的相应职责,
或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
  • 开放封闭 o - open
一个软件实体应当对扩展开放,对修改关闭。
即软件实体应尽量在不修改原有代码的情况下进行扩展。
  • 里氏替换 l - lis
所有引用基类对象的地方能够透明地使用其子类的对象
  • 接口分离 i - interface
使用多个专门的接口,而不使用单一的总接口,
即客户端不应该依赖那些它不需要的接口。

  • 依赖倒置 d - dependence
抽象不应该依赖于具体类,具体类应当依赖于抽象。
换言之,要针对接口编程,而不是针对实现编程
  • 迪米特 d - demeter
一个软件实体应当尽可能少地与其他实体发生相互作用
最少知道

二、二十三种设计模式

创建型 5
对象创建, 关注如何创建对象
结构型 7 (3+4)
对象组合,以便形成更好、更灵活的结构
行为型 11 (4+3+4)
对象交互,协作完成一个整体任务

三、UML类图

1. 依赖

与关联不同,它是一种临时性的关系。 用一条带有箭头的虚线表示。

image

2. 关联

单向,用一个带箭头的直线表示,双向,用一个不带箭头的直线表示。自关联

(1)单向关联 image

(2)双向关联 image

(3)自关联 image

3. 聚合

整体和部分不是强依赖关系,强调是“整体”包含“部分”,但是“部分”可以脱离“整体”而单独存在。用带空心菱形和箭头的直线表示

image

4. 组合

强调部分和整体关系,整体和部分是强依赖关系。用一个带实心菱形和箭头的直线表示

image

5. 实现

用带空心三角形的虚线表示

image

6. 继承

用带空心三角形的直线表示

image

四、创建型模式

1、单例
单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,并提供一个访问它的全剧访问点。

保证一个类只有一个实例, 并提供一个访问该实例的全局节点。
单例模式结构

2、简单工厂
专门定义一个类(工厂类)来负责创建其他类的实例。
可以根据创建方法的参数来返回不同类的实例,
被创建的实例通常都具有共同的父类

3、工厂方法
定义一个用于创建对象的接口,让子类决定实例化哪一个类。
Factory Method使一个类的实例化延迟到其子类。

其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型
┌─────────────┐      ┌─────────────┐
│   Product   │      │   Factory   │
└─────────────┘      └─────────────┘
       ▲                    ▲
       │                    │
┌─────────────┐      ┌─────────────┐
│ ProductImpl │◀─ ─ ─│ FactoryImpl │
└─────────────┘      └─────────────┘

工厂方法模式结构

4、抽象工厂
它能创建一系列相关的对象, 而无需指定其具体类

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
                                ┌────────┐
                             ─ ▶│ProductA│
┌────────┐    ┌─────────┐   │   └────────┘
│ Client │─ ─▶│ Factory │─ ─
└────────┘    └─────────┘   │   ┌────────┐
                   ▲         ─ ▶│ProductB│
           ┌───────┴───────┐    └────────┘
           │               │
      ┌─────────┐     ┌─────────┐
      │Factory1 │     │Factory2 │
      └─────────┘     └─────────┘
           │   ┌─────────┐ │   ┌─────────┐
            ─ ▶│ProductA1│  ─ ▶│ProductA2│
           │   └─────────┘ │   └─────────┘
               ┌─────────┐     ┌─────────┐
           └ ─▶│ProductB1│ └ ─▶│ProductB2│
               └─────────┘     └─────────┘
抽象工厂设计模式

5、生成器
一种创建型设计模式, 使你能够分步骤创建复杂对象。
该模式允许你使用相同的创建代码生成不同类型和形式的对象

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
生成器设计模式结构

6、原型
原型模式(Prototype Pattern): 使用原型实例指定待创建对象的类型,
并且通过复制这个原型来创建新的对象。

使你能够复制已有对象, 而又无需使代码依赖它们所属的类
原型设计模式的结构

五、结构型模式

1、适配器
使接口不兼容的对象能够相互合作

将一个类的接口转换成客户希望的另外一个接口,
使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

对象适配器 适配器设计模式的结构(对象适配器)

类适配器 适配器设计模式(类适配器)

2、装饰器
             ┌───────────┐
             │ Component │
             └───────────┘
                   ▲
      ┌────────────┼─────────────────┐
      │            │                 │
┌───────────┐┌───────────┐     ┌───────────┐
│ComponentA ││ComponentB │...  │ Decorator │
└───────────┘└───────────┘     └───────────┘
                                     ▲
                              ┌──────┴──────┐
                              │             │
                        ┌───────────┐ ┌───────────┐
                        │DecoratorA │ │DecoratorB │...
                        └───────────┘ └───────────┘

装饰设计模式的结构

3、桥接
可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 
从而能在开发时分别使用。

将抽象部分与它的实现部分分离,使它们都可以独立地变化。
       ┌───────────┐
       │    Car    │
       └───────────┘
             ▲
             │
       ┌───────────┐       ┌─────────┐
       │RefinedCar │ ─ ─ ─▶│ Engine  │
       └───────────┘       └─────────┘
             ▲                  ▲
    ┌────────┼────────┐         │ ┌──────────────┐
    │        │        │         ├─│  FuelEngine  │
┌───────┐┌───────┐┌───────┐     │ └──────────────┘
│BigCar ││TinyCar││BossCar│     │ ┌──────────────┐
└───────┘└───────┘└───────┘     ├─│ElectricEngine│
                                │ └──────────────┘
                                │ ┌──────────────┐
                                └─│ HybridEngine │
                                  └──────────────┘

桥接设计模式

4、组合
使用它将对象组合成树状结构,
并且能像使用独立对象一样使用它们

将对象组合成树形结构以表示“部分-整体”的层次结构,
使得用户对单个对象和组合对象的使用具有一致性。
             ┌───────────┐
             │   Node    │
             └───────────┘
                   ▲
      ┌────────────┼────────────┐
      │            │            │
┌───────────┐┌───────────┐┌───────────┐
│ElementNode││ TextNode  ││CommentNode│
└───────────┘└───────────┘└───────────┘

组合设计模式的结构

5、外观
为程序库、 框架或其他复杂类提供一个简单的接口。

为子系统中的一组接口提供一个一致的界面。
Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
外观设计模式的结构

6、代理
让你能够提供对象的替代品或其占位符。
代理控制着对于原对象的访问,
并允许在将请求提交给对象前后进行一些处理。

为其他对象提供一种代理以控制对这个对象的访问。
代理设计模式的结构

7、享元
通过共享多个对象所共有的相同状态,
让你能在有限的内存容量中载入更多对象

运用共享技术有效地支持大量细粒度的对象。
享元设计模式的结构

六、行为型模式

1、责任链
允许你将请求沿着处理者链进行发送。 
收到请求后, 每个处理者均可对请求进行处理, 
或将其传递给链上的下个处理者。

使多个对象都有机会处理请求,
从而避免请求的发送者和接收者之间的耦合关系。
将这些对象连成一条链,并沿着这条链传递该请求,
直到有一个对象处理它为止
     ┌─────────┐
     │ Request │
     └─────────┘
          │
┌ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ┐
          ▼
│  ┌─────────────┐  │
   │ ProcessorA  │
│  └─────────────┘  │
          │
│         ▼         │
   ┌─────────────┐
│  │ ProcessorB  │  │
   └─────────────┘
│         │         │
          ▼
│  ┌─────────────┐  │
   │ ProcessorC  │
│  └─────────────┘  │
          │
└ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ┘
          │
          ▼

2、观察者
定义一种订阅机制,可在对象事件发生时通知多个 “观察” 该对象的其他对象。

3、命令
它可将请求转换为一个包含与请求相关的所有信息的独立对象。
该转换让你能根据不同的请求将方法参数化、
延迟请求执行或将其放入队列中, 且能实现可撤销操作
┌──────┐      ┌───────┐
│Client│─ ─ ─▶│Command│
└──────┘      └───────┘
                  │  ┌──────────────┐
                  ├─▶│ CopyCommand  │
                  │  ├──────────────┤
                  │  │editor.copy() │─ ┐
                  │  └──────────────┘
                  │                    │  ┌────────────┐
                  │  ┌──────────────┐   ─▶│ TextEditor │
                  └─▶│ PasteCommand │  │  └────────────┘
                     ├──────────────┤
                     │editor.paste()│─ ┘
                     └──────────────┘

4、备忘录
备忘录模式(Memento Pattern):在不破坏封装的前提下,
捕获一个对象的内部状态,并在该对象之外保存这个状态,
这样可以在以后将对象恢复到原先保存的状态。
它是一种对象行为型模式,其别名为Token。

基于嵌套类的实现

基于中间接口的实现

封装更加严格的实现

5、状态
允许一个对象在其内部状态改变时改变它的行为。
对象看起来似乎修改了它的类。

把不同的状态逻辑,分离到不同的状态类中,
使得增加新状态更容易

6、策略
定义一系列的算法,把它们一个个封装起来,
并且使它们可相互替换。
本模式使得算法可独立于使用它的客户而变化。

策略模式是一种行为设计模式, 
它能让你定义一系列算法, 
并将每种算法分别放入独立的类中, 
以使算法的对象能够相互替换

策略是一种行为设计模式, 它将一组行为转换为对象, 并使其在原始上下文对象内部能够相互替换

┌───────────────┐      ┌─────────────────┐
│DiscountContext│─ ─ ─▶│DiscountStrategy │
└───────────────┘      └─────────────────┘
                                ▲
                                │ ┌─────────────────────┐
                                ├─│UserDiscountStrategy │
                                │ └─────────────────────┘
                                │ ┌─────────────────────┐
                                ├─│PrimeDiscountStrategy│
                                │ └─────────────────────┘
                                │ ┌─────────────────────┐
                                └─│OverDiscountStrategy │
                                  └─────────────────────┘

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

简单来说:

在超类中,定义算法框架,然后在子类中重写算法的特定步骤

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


9、迭代器
提供一种方法顺序访问一个聚合对象中的各个元素,
而又不需要暴露该对象的内部表示。

让你能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。
迭代器设计模式的结构

10、访问者
表示一个作用于某对象结构中的各元素的操作。
它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

它能将算法与其所作用的对象隔离开来
   ┌─────────┐       ┌───────────────────────┐
   │ Client  │─ ─ ─ ▶│        Visitor        │
   └─────────┘       ├───────────────────────┤
        │            │visitElementA(ElementA)│
                     │visitElementB(ElementB)│
        │            └───────────────────────┘
                                 ▲
        │                ┌───────┴───────┐
                         │               │
        │         ┌─────────────┐ ┌─────────────┐
                  │  VisitorA   │ │  VisitorB   │
        │         └─────────────┘ └─────────────┘
        ▼
┌───────────────┐        ┌───────────────┐
│ObjectStructure│─ ─ ─ ─▶│    Element    │
├───────────────┤        ├───────────────┤
│handle(Visitor)│        │accept(Visitor)│
└───────────────┘        └───────────────┘
                                 ▲
                        ┌────────┴────────┐
                        │                 │
                ┌───────────────┐ ┌───────────────┐
                │   ElementA    │ │   ElementB    │
                ├───────────────┤ ├───────────────┤
                │accept(Visitor)│ │accept(Visitor)│
                │doA()          │ │doB()          │
                └───────────────┘ └───────────────┘

访问者设计模式的结构

11、中介者
中介者模式是一种行为设计模式,能让你减少对象之间混乱无序的依赖关系。
该模式会限制对象之间的直接交互,迫使它们通过一个中介者对象进行合作。
            ┌─────────────────┐
     ┌─────▶│  CheckBox List  │
     │      └─────────────────┘
     │      ┌─────────────────┐
     │ ┌───▶│SelectAll Button │
     ▼ ▼    └─────────────────┘
┌─────────┐
│Mediator │
└─────────┘
     ▲ ▲    ┌─────────────────┐
     │ └───▶│SelectNone Button│
     │      └─────────────────┘
     │      ┌─────────────────┐
     └─────▶│ Inverse Button  │
            └─────────────────┘

中介者设计模式的结构

参考

学习并理解 23 种设计模式

Design-Patterns-In-Swift

廖雪峰 - 设计模式

设计模式,翻译,推荐,图示

图说设计模式

五分钟读懂UML类图