Skip to content
Yunhan's Lab
Go back

Design Pattern Notes

Updated:
Edit page

1. UML (Unified Modeling Language)

Structure of UML (USBIE)

UML结构图

2. Principle of OO Programmingc

SOLID (给例子问违反了哪个)+CL

Single Responsibility Principle (每个类只能有一个责任)

Open Closed Principle (向扩展开放,向更改关闭)

Liskov Substitution Principle (子类型必须能够完全替换其父类型!)

Interface Segregation Principle (使用接口的对象可以自由选择使用的内容)(接口应小而专一,避免“胖接口”)

Dependency Inversion Principle (高层模块与底层模块分离,使它们都依赖于抽象,而不是具体实现)

Composite Reuse Principle

Law of Demeter(最少知识原则)

3. Overview of DP

模式的基本组成:

模式的一般要素:

分类方式:

按目的分类:

  1. 创建型模式(Creational):用于创建对象
  2. 结构型模式(Structural):组织多个对象形成高效结构
  3. 行为型模式(Behavioral):描述类与对象间的交互和职责分配

![](@/assets/images/design-pattern/屏幕截图 2025-11-23 124910.png)

设计模式的优点(Surfeb)

  1. 经验总结 (Summary of experiences):汇集多位专家经验,以标准化形式供开发者使用
  2. 通用语言(Universal language):提供通用术语,便于开发者沟通和理解设计概念
  3. 促进重用(Reuse successful designs and architectures):使人们能更轻松方便地重用成功的设计和架构
  4. 提高灵活性 (make design solution more Flexible):使设计解决方案更加灵活且易于修改
  5. 提升效率 (enhance development Efficiency):提供经过验证的开发范式,提高软件开发效率和软件质量
  6. 辅助学习 (assists Beginners):帮助初学者深入理解面向对象概念,提升软件设计能力和代码质量

4. Simple Factory (18-19.6)

定义

意图

  1. 封装创建逻辑:在不向客户端暴露实例化逻辑的情况下创建对象。(符合open-close原则的思想,但对扩展不支持)
  2. 面向接口编程:通过一个共同的接口来引用所创建的对象。(符合Dependency Inversion原则

结构

简单工厂模式包含三个核心角色:

角色描述示例(电视机工厂)
Factory(工厂)负责创建所有具体产品的实例。它包含核心的创建逻辑。TVFactory
Product(抽象产品)所有具体产品类的父类,定义了产品的公共接口。TV
ConcreteProduct(具体产品)工厂类创建的目标,实现了抽象产品接口。HaierTV, HisenseTV

simple factory

优点

  1. 解耦:客户端与具体产品类解耦。
  2. 客户端简单:客户端无需知道具体类名,只需传入参数。
  3. 便于管理:可以通过配置文件(如XML)来管理参数和具体类的映射关系,无需修改代码即可替换产品。

缺点

  1. 违反开闭原则:这是最严重的缺点。当需要增加新的产品时,必须修改工厂类的源代码(例如,在 switchif-else 语句中增加新的分支)。
  2. 工厂职责过重:工厂类集中了所有产品的创建逻辑,一旦出错,整个系统受影响。
  3. 系统复杂度增加:引入了额外的工厂类。
  4. 静态方法限制:通常使用静态工厂方法,这导致工厂类无法通过继承来扩展行为。

5. Factory Pattern

Virtual Constructor (虚拟构造器) or Polymorphic Factory (多态工厂)

定义

意图

  1. 定义创建接口:定义一个用于创建对象的接口。
  2. 子类决定实例化:将实际创建对象的工作推迟到子类中完成。
  3. 面向接口编程:通过共同的接口来引用新创建的对象。

结构

工厂方法模式包含四个核心角色:

角色描述示例(电视机工厂)
Product(抽象产品)定义产品的接口。TV
ConcreteProduct(具体产品)实现抽象产品接口。HaierTV, HisenseTV
Factory(抽象工厂)声明工厂方法,返回一个抽象产品类型的对象。TVFactory
ConcreteFactory(具体工厂)重写工厂方法,返回一个具体产品实例。HaierTVFactory, HisenseTVFactory

Factory

工作流程

  1. 客户端依赖于抽象工厂 (TVFactory)。
  2. 在运行时,客户端获得一个具体工厂 (如 HaierTVFactory) 的实例。
  3. 客户端调用工厂的 factoryMethod() (如 produceTV())。
  4. 具体工厂创建并返回对应的具体产品 (如 HaierTV)。
  5. 客户端通过抽象产品接口 (TV) 使用该对象。

与简单工厂模式的对比

特性简单工厂模式工厂方法模式
工厂角色一个具体的类,包含所有创建逻辑。一个抽象接口和多个具体实现类。
扩展性违反开闭原则。新增产品必须修改工厂类源代码。符合开闭原则。新增产品只需添加新的工厂类。
复杂度结构简单,类少。结构更复杂,类的数量成对增加。
职责工厂类职责过重,是“万能”的。职责分解,每个具体工厂只负责一种产品。

6. Abstract Factory

定义

关键概念:产品等级结构与产品族

结构

抽象工厂模式包含四个核心角色:

角色描述示例(电器工厂)
AbstractFactory(抽象工厂)声明一组用于创建一族产品的方法。EFactory
ConcreteFactory(具体工厂)实现抽象工厂的接口,创建属于特定产品族的具体产品。HaierFactory, TCLFactory
AbstractProduct(抽象产品)为每种产品声明接口。Television, AirConditioner
ConcreteProduct(具体产品)定义具体工厂生产的具体产品对象,实现抽象产品接口。HaierTelevision, TCLTelevision, HaierAirConditioner, TCLAirConditioner

Abstract Factory

与工厂方法模式的对比

这是理解抽象工厂模式的关键:

维度工厂方法模式抽象工厂模式
核心维度一维:只关注一个产品等级结构(如:电视机)。二维:关注多个产品等级结构构成的产品族(如:电视机 + 空调)。
创建目标创建一种产品。创建一族相关的产品。
工厂职责一个具体工厂只负责创建一个具体产品一个具体工厂负责创建一个产品族所有产品
适用场景系统只有一个产品等级结构,或不需要关心产品之间的约束。系统有多个产品等级结构,且产品之间有关联,需要保证一起使用同一家族的产品。

简单比喻

优点

  1. 分离具体类:客户端与具体产品的创建过程分离。
  2. 保证产品族一致性:确保客户端始终使用同一产品族的对象。这是其最大优势。
  3. 符合开闭原则(对产品族)增加一个新的产品族(如新增一个 HisenseFactory)非常方便,无需修改现有代码。

缺点

  1. 难以支持新的产品种类:这是其最大缺点。如果要在所有产品族中增加一个新的产品种类(如在 EFactory 中增加 produceRefrigerator() 方法),就需要修改抽象工厂接口及其所有具体工厂子类,这违反了开闭原则
public interface AbstractFactory{
    public AbstractProductA createProductA();
    public AbstractProductB createProductB();
}
public interface AbstractProductA{
    //
}
public class ProductA1 implements AbstractProductA{
    system.out.print("ProductA1:: a product is built!");
}
public class ConcreteFactory1 implements AbstractFactory{
    public AbstractProductA createProductA(){
        return new ProductA1();
    }
    public AbstractProductB createProductB(){
        return new ProductB1;
    }
}

简单工厂、工厂模式和抽象工厂 (18-19.7)

The following code uses the ( ) pattern:

A. Simple Factory

B. Factory Method

C. Abstract Factory

D. No design patterns are used

public abstract class ExchangeMethod { 
	public abstract void process (  ); 
} 
public class DigitalCurrency extends ExchangeMethod{ 
	public void process(  ){...} 
} 
public class CreditCard extends ExchangeMethod{ 
	public void process(  ){...} 
} 
... 
public class Factory{ 
    public static ExchangeMethod createProduct(String type){ 
        switch(type){ 
            case"DigitalCurrency": 
            return new DigitalCurrency(  );break; 
            case"CreditCard": 
            return new CreditCard(  );break;
            ...
        }
    }
}

三种工厂模式核心区别总结

为了清晰区分,我们从四个维度来对比:

维度简单工厂工厂方法抽象工厂
工厂角色一个具体类,包含所有创建逻辑一个抽象接口/类 + 多个具体工厂子类一个抽象接口/类 + 多个具体工厂子类
创建方式静态方法,根据参数创建不同产品每个具体工厂只创建一种具体产品每个具体工厂创建一族相关产品
扩展性违反开闭原则 新增产品必须修改工厂类符合开闭原则 新增产品时,添加新的具体工厂即可对产品族符合开闭原则 新增产品族容易,新增产品种类困难
结构复杂度简单,类少较复杂,类成对增加(一个产品一个工厂)最复杂,涉及多个产品等级结构

一句话概括核心思想


如何快速识别

  1. 看到 static 工厂方法 + switch/if + 参数决定对象 → 简单工厂
  2. 看到工厂是接口/抽象类 + 每个具体产品对应一个具体工厂子类 → 工厂方法
  3. 看到一个具体工厂能创建多个不同类的产品(这些产品是相关的)→ 抽象工厂

7. Builder

定义

意图

结构

建造者模式包含四个核心角色:

角色描述示例(KFC套餐)
Builder(抽象建造者)为创建一个产品对象的各个部件指定抽象接口。MealBuilder
ConcreteBuilder(具体建造者)实现Builder的接口,定义并明确它所创建的复杂对象的各个部件。提供检索产品的接口。SubMealBuilderA, SubMealBuilderB
Director(指挥者)构建一个使用Builder接口的对象。它安排复杂对象的构建次序。KFCWaiter
Product(产品)被构建的复杂对象。包含多个组成部分。Meal

Builder

优点

  1. 良好的封装性:客户端不必知道产品内部组成的细节。
  2. 构建过程独立:将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象
  3. 易于扩展符合开闭原则。要增加新的具体建造者非常方便,无需修改现有代码。
  4. 精细控制:可以更精细地控制产品的创建过程。

缺点

  1. 产品共性要求高:所创建的产品需要有较多的共同点,如果产品之间差异非常大,则不适合使用建造者模式。
  2. 系统复杂性增加:如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,使得系统变得庞大。

适用场景

核心思想总结

建造者模式的精髓在于 “流程固定,部件可变”

这使得它在创建需要多个步骤、且步骤相同但结果不同的复杂对象时,非常有用。它是对工厂模式(关注整体实例化)的一种补充,更侧重于对象的组装过程

8.5 Prototype

定义

意图

通过复制一个原型对象来创建多个与其相同的对象。

结构

原型模式包含三个核心角色:

角色描述示例(邮件复制)
Prototype(抽象原型)声明克隆方法的接口。Cloneable 接口
ConcretePrototype(具体原型)实现克隆方法,返回自身的一个副本。Email
Client(客户端)让一个原型克隆自身从而创建一个新对象。使用Email的客户端

Prototype

浅克隆(Shallow Clone) vs 深克隆(Deep Clone)

类型特点图示说明
浅克隆只复制对象本身和其值类型成员,引用类型成员只复制引用(指向同一个对象)。原型对象和克隆对象共享附件
深克隆复制对象本身以及所有引用类型成员指向的对象原型对象和克隆对象各有自己的附件副本

优点

  1. 简化创建过程:通过复制现有实例来创建新实例,效率高。
  2. 良好的扩展性:可以动态添加产品类。
  3. 简化创建结构:不需要专门的工厂类,产品自己完成克隆。
  4. 可以保存对象状态:通过深克隆可以保存对象状态,便于实现撤销操作。

缺点

  1. 违反开闭原则:需要为每个类提供克隆方法,修改现有类时需要修改源代码。
  2. 深克隆实现复杂:实现深克隆需要编写复杂的代码。
  3. 对继承关系不友好:如果原型类处于继承层次中,可能需要在所有层次上都正确实现克隆。

适用场景

典型应用

8. Singlton

定义

三个核心特征

  1. 一个类在内存中只有一个实例
  2. 该实例必须由这个类自行创建
  3. 该实例必须能够被整个系统访问

结构

单例模式的结构非常简单,只包含一个角色:

角色描述
Singleton(单例)负责创建和管理自己的唯一实例,并提供全局访问点

Singlton

1. 懒汉式(Lazy Singleton)

public class Singleton {
    private static Singleton instance = null;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) { // 多线程环境下不安全
            instance = new Singleton();
        }
        return instance;
    }
}

2. 饿汉式(Eager Singleton)

public class EagerSingleton {
    private static final EagerSingleton instance = new EagerSingleton();
    private EagerSingleton() {}
    public static EagerSingleton getInstance() {
        return instance; // 直接返回预先创建好的实例
    }
}

优点

  1. 严格控制实例:提供了对唯一实例的受控访问
  2. 节约资源:只存在一个对象,可以节约系统资源,提高系统性能
  3. 允许可变数量的实例:可以扩展为多例模式

缺点

  1. 难以扩展:由于没有抽象层,单例类的扩展有很大困难
  2. 职责过重:单例类既提供了业务方法,又负责创建自身实例,某种程度上违背了”单一职责原则”
  3. 状态丢失:在一些依赖于垃圾回收机制的环境中,如果单例对象长时间不被使用,可能会被回收,导致状态丢失

五、适用场景

Adapter

定义

意图

结构

适配器模式包含三个核心角色:

角色描述示例(机器人模仿狗)
Target abstract class(目标抽象类)定义客户要使用的特定领域的接口。Robot
Adapter(适配器)调用另一个接口,作为一个转换器。DogAdapter
Adaptee(适配者)被适配的角色,包含需要使用的接口。Dog
Class AdapterObject Adapter
Class adaptorobject adaptor

优点

  1. 解耦目标与适配者
  2. 提高类的复用性
  3. 灵活性和扩展性好
  4. 类适配器:可以重写适配者的方法
  5. 对象适配器:可以适配多个不同的适配者

缺点

  1. 类适配器
    • 一次只能适配一个适配者
    • 不能适配final类
  2. 对象适配器:重写适配者的方法比较麻烦

Bridge

定义

核心动机:解决多维度变化

结构

桥接模式包含四个核心角色:

角色描述示例(画笔)
Abstraction(抽象类)定义抽象接口,维护一个实现类对象的引用。Pen
RefinedAbstraction(扩充抽象类)扩充由抽象类定义的接口。SmallPen, MiddlePen, BigPen
Implementor(实现类接口)定义实现类的接口。Color
ConcreteImplementor(具体实现类)实现实现类接口。Red, Green, Blue, White, Black

Bridge

优点

  1. 分离抽象与实现:真正的解耦,两者可以独立变化。
  2. 取代多层继承:极大地减少了子类的数量。
  3. 提高扩展性:扩展任意一个维度都无需修改现有系统,符合开闭原则
  4. 细节对客户透明:客户无需关心实现的细节。

缺点

  1. 增加理解难度:要求开发者在设计之初就基于抽象层进行思考。
  2. 识别维度困难:正确识别系统中两个独立变化的维度并不容易。

适用场景

Composite

核心定义

意图

结构

角色描述示例(文件系统)
Component(抽象组件)定义组合中对象的统一接口,声明访问和管理子组件的方法。AbstractElement
Leaf(叶子组件)表示组合中的叶子节点,没有子节点,实现组件接口的业务方法。File
Composite(容器组件)表示组合中的容器节点,包含子组件集合,实现管理子组件的方法,并在业务方法中递归调用子组件。Folder

两种实现变体

透明组合模式安全组合模式
特点在抽象组件中声明所有管理子对象的方法只在容器组件中声明管理子对象的方法
优点客户端可以完全一致地对待所有对象编译期类型安全
缺点不够安全,叶子对象可能抛出不支持的操作异常客户端需要区分叶子与容器,失去透明性

优点

缺点

适用场景

根据课件总结的适用情况:

Decorate

定义

装饰模式是一种结构型设计模式,它动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。

核心意图

  1. 动态扩展 - 在不改变对象自身的情况下,动态地添加功能
  2. 替代继承 - 提供继承之外的另一种扩展功能的方式
  3. 透明增强 - 客户端无需知道对象是否被装饰,可以像使用原始对象一样使用装饰后的对象

结构总结

角色描述示例(变形金刚)
Component(抽象组件)定义对象的统一接口,可以被动态添加职责。Transformer
ConcreteComponent(具体组件)定义具体的对象,将要被添加职责的原始对象。Car
Decorator(抽象装饰类)维护一个指向Component对象的引用,并定义与Component一致的接口。TransformerDecorator
ConcreteDecorator(具体装饰类)向组件添加具体的职责,在调用原始方法前后执行附加行为。RobotDecorator, AirplaneDecorator

Decorate

优点

缺点

Facade(object structural pattern)

定义

外观模式是一种结构型设计模式,它为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易使用。

意图

  1. 简化接口 - 为复杂子系统提供简单统一的入口
  2. 解耦客户端 - 将客户端与子系统的复杂实现分离
  3. 降低依赖 - 减少客户端对子系统内部组件的直接依赖

外观模式示意图

结构

角色描述示例(电器开关)
Facade(外观类)知道哪些子系统负责处理请求,将客户端请求代理给适当的子系统对象GeneralSwitchFacade
SubSystem(子系统)实现子系统的功能,处理外观类指派的任务,子系统之间可以相互交互Light, Fan, AirConditioner, Television
Client(客户端)通过外观接口与子系统交互,无需直接访问子系统开关使用者

优点

缺点

Chain of Responsibility

定义

责任链模式是一种行为型设计模式,它通过给多个对象处理请求的机会,避免请求发送者与接收者耦合。将接收对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

意图

  1. 解耦发送者与接收者 - 发送者不需要知道具体由哪个接收者处理请求
  2. 动态组织处理链 - 可以在运行时动态改变处理请求的对象链
  3. 多对象协作 - 让多个对象都有机会处理请求

结构

角色描述示例(请假审批)
Handler(抽象处理者)定义处理请求的接口,维护后继处理者的引用Leader
ConcreteHandler(具体处理者)处理自己负责的请求,可访问后继者,可转发请求Director, Manager, GeneralManager
Client(客户端)创建处理链,向链头的处理者提交请求请假申请系统
Request(请求)封装请求信息,在链中传递LeaveRequest

Chain of responsibility

优点

缺点

Command

定义

命令模式是一种行为型设计模式,它将一个请求封装为一个对象,从而让你可以用不同的请求对客户进行参数化,支持请求的排队、记录日志,以及支持可撤销的操作。

意图

  1. 请求封装 - 将请求封装成独立的对象
  2. 解耦调用者与执行者 - 调用者不需要知道具体的执行细节
  3. 支持事务操作 - 实现请求的排队、日志、撤销等功能

结构

角色描述示例(电视遥控器)
Command(抽象命令)声明执行操作的接口AbstractCommand
ConcreteCommand(具体命令)将一个接收者对象绑定于一个动作,实现执行方法TVOpenCommand, TVCloseCommand, TVChangeCommand
Invoker(调用者)要求命令执行请求Controller(遥控器)
Receiver(接收者)知道如何实施与执行一个请求相关的操作Television
Client(客户端)创建具体命令对象并设定其接收者遥控器配置程序

Command

优点

缺点

Iterator

定义

迭代器模式是一种行为型设计模式,它提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。

意图

  1. 封装遍历逻辑 - 将遍历算法从聚合对象中分离出来
  2. 统一访问接口 - 为不同的聚合结构提供一致的遍历方式
  3. 保护内部结构 - 客户端无需了解聚合对象的内部实现细节

结构

角色描述示例(电视系统)
Iterator(抽象迭代器)定义访问和遍历元素的接口TvIterator
ConcreteIterator(具体迭代器)实现迭代器接口,跟踪遍历位置SkyworthIterator, TCLIterator
Aggregate(抽象聚合类)定义创建迭代器对象的接口Television
ConcreteAggregate(具体聚合类)实现创建迭代器的接口,返回具体迭代器实例SkyworthTelevision, TCLTelevision
Client(客户端)通过迭代器接口访问聚合对象元素遥控器使用者

Iterator

优点

缺点

Strategy

定义

策略模式是一种行为型设计模式,它定义了一系列算法,将每个算法封装起来,并使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户端。

意图

  1. 算法封装 - 将不同的算法封装在独立的策略类中
  2. 灵活替换 - 客户端可以在运行时动态选择不同的策略
  3. 消除条件判断 - 避免使用复杂的条件语句来选择算法

结构

角色描述示例(排序算法)
Context(环境类)维护对策略对象的引用,可动态切换策略ArrayHandler
Strategy(抽象策略)定义所有支持算法的公共接口Sort
ConcreteStrategy(具体策略)实现抽象策略定义的接口,提供具体算法BubbleSort, SelectionSort, InsertionSort

Strategy

优点

缺点


Edit page
Share this post on:

Previous Post
PCS notes