一、装饰器模式(Decorator)
1.1 模式定义
动态地给一个对象增加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
核心要点:
- 装饰器和被装饰对象继承自同一个接口或基类
- 装饰器包装被装饰对象,在调用前后可添加额外逻辑
- 可以无限嵌套装饰
1.2 结构
Component(抽象组件)
↑ extends
ConcreteComponent(具体组件)
↑ wraps
Decorator(装饰器)
↑ extends
ConcreteDecorator(具体装饰器)
1.3 代码实现
#include <iostream>
#include <string>
// 抽象组件:饮料
class IBeverage {
public:
virtual ~IBeverage() {}
virtual std::string description() const = 0;
virtual double cost() const = 0;
};
// 具体组件:咖啡
class Coffee : public IBeverage {
public:
std::string description() const override {
return "Coffee";
}
double cost() const override {
return 20.0;
}
};
// 装饰器基类
class BeverageDecorator : public IBeverage {
protected:
IBeverage* m_beverage;
public:
BeverageDecorator(IBeverage* beverage) : m_beverage(beverage) {}
std::string description() const override {
return m_beverage->description();
}
double cost() const override {
return m_beverage->cost();
}
};
// 具体装饰器:牛奶
class MilkDecorator : public BeverageDecorator {
public:
MilkDecorator(IBeverage* beverage) : BeverageDecorator(beverage) {}
std::string description() const override {
return m_beverage->description() + " + Milk";
}
double cost() const override {
return m_beverage->cost() + 5.0;
}
};
// 具体装饰器:糖
class SugarDecorator : public BeverageDecorator {
public:
SugarDecorator(IBeverage* beverage) : BeverageDecorator(beverage) {}
std::string description() const override {
return m_beverage->description() + " + Sugar";
}
double cost() const override {
return m_beverage->cost() + 2.0;
}
};
int main() {
// 原味咖啡
IBeverage* coffee = new Coffee();
std::cout << coffee->description() << " = " << coffee->cost() << std::endl;
// 咖啡 + 牛奶
IBeverage* milkCoffee = new MilkDecorator(coffee);
std::cout << milkCoffee->description() << " = " << milkCoffee->cost() << std::endl;
// 咖啡 + 牛奶 + 糖
IBeverage* sweetMilkCoffee = new SugarDecorator(milkCoffee);
std::cout << sweetMilkCoffee->description() << " = " << sweetMilkCoffee->cost() << std::endl;
delete sweetMilkCoffee;
delete milkCoffee;
delete coffee;
return 0;
}
1.4 流程图
main
|
v
[创建Coffee对象]
|
v
[输出: Coffee = 20]
|
v
[创建MilkDecorator(Coffee)]
|
v
[输出: Coffee + Milk = 25]
|
v
[创建SugarDecorator(MilkDecorator(Coffee))]
|
v
[输出: Coffee + Milk + Sugar = 27]
|
v
[依次delete释放内存]
1.5 逐行解析
// 抽象组件,定义饮料的共同接口
class IBeverage {
public:
virtual ~IBeverage() {} // 虚析构,保证多态删除安全
virtual std::string description() const = 0; // 描述
virtual double cost() const = 0; // 价格
};
// 具体组件,最基础的咖啡
class Coffee : public IBeverage {
std::string description() const override {
return "Coffee"; // 返回描述
}
double cost() const override {
return 20.0; // 价格20元
}
};
// 装饰器基类,关键:包含一个组件指针
class BeverageDecorator : public IBeverage {
protected:
IBeverage* m_beverage; // 被包装的组件
public:
BeverageDecorator(IBeverage* beverage) : m_beverage(beverage) {}
// 默认委托给被包装对象
std::string description() const override {
return m_beverage->description();
}
double cost() const override {
return m_beverage->cost();
}
};
// 具体装饰器:添加牛奶
class MilkDecorator : public BeverageDecorator {
public:
MilkDecorator(IBeverage* beverage) : BeverageDecorator(beverage) {}
std::string description() const override {
// 在原有基础上添加 "+ Milk"
return m_beverage->description() + " + Milk";
}
double cost() const override {
// 在原有价格上加5元
return m_beverage->cost() + 5.0;
}
};
1.6 对比表
| 特性 |
继承方式 |
灵活性 |
代码复杂度 |
| 装饰器模式 |
组合 |
高,可动态添加 |
中等 |
| 继承子类 |
继承 |
低,编译时确定 |
简单 |
1.7 面试追问 FAQ
| 问题 |
回答 |
| 装饰器与代理模式的区别? |
装饰器侧重于功能增强,代理模式侧重于控制访问 |
| 装饰器可以嵌套几层? |
理论上无限,但实际中2-4层为宜 |
| 如何解除装饰关系? |
通过接口向上转型后,再提取原始对象 |
二、组合模式(Composite)
2.1 模式定义
将对象组合成树型结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
核心要点:
- 抽象组件定义共同接口
- 叶子节点和组合节点实现相同的接口
- 组合节点可以包含叶子或其他组合节点
2.2 结构
Component(抽象组件)
|-- Leaf(叶子节点): 实现具体操作
|-- Composite(组合节点): 包含叶子列表,实现操作时遍历所有子节点
2.3 代码实现
#include <iostream>
#include <vector>
#include <string>
// 抽象组件:文件系统节点
class IFileSystemNode {
public:
virtual ~IFileSystemNode() {}
virtual size_t size() const = 0;
virtual void display(int depth = 0) const = 0;
};
// 叶子节点:文件
class File : public IFileSystemNode {
private:
std::string m_name;
size_t m_size;
public:
File(const std::string& name, size_t size) : m_name(name), m_size(size) {}
size_t size() const override {
return m_size;
}
void display(int depth = 0) const override {
std::string indent(depth * 2, '-');
std::cout << indent << m_name << " (" << m_size << " KB)" << std::endl;
}
};
// 组合节点:文件夹
class Folder : public IFileSystemNode {
private:
std::string m_name;
std::vector<IFileSystemNode*> m_children;
public:
Folder(const std::string& name) : m_name(name) {}
void add(IFileSystemNode* node) {
m_children.push_back(node);
}
size_t size() const override {
size_t total = 0;
for (const auto& child : m_children) {
total += child->size();
}
return total;
}
void display(int depth = 0) const override {
std::string indent(depth * 2, '-');
std::cout << indent << m_name << "/ (total: " << size() << " KB)" << std::endl;
for (const auto& child : m_children) {
child->display(depth + 1);
}
}
};
int main() {
Folder* root = new Folder("root");
File* f1 = new File("a.txt", 100);
File* f2 = new File("b.txt", 200);
Folder* subFolder = new Folder("sub");
File* f3 = new File("c.txt", 300);
subFolder->add(f3);
root->add(f1);
root->add(f2);
root->add(subFolder);
root->display();
delete root;
return 0;
}
2.4 流程图
main
|
v
[创建root文件夹]
|
v
[创建文件a.txt(100KB), b.txt(200KB)]
|
v
[创建sub文件夹]
|
v
[创建文件c.txt(300KB)]
|
v
[sub.add(c.txt)]
|
v
[root.add(a.txt), root.add(b.txt), root.add(sub)]
|
v
[root.display()]
|
+-- root/(total: 600KB)
+-- a.txt(100KB)
+-- b.txt(200KB)
+-- sub/(total: 300KB)
+-- c.txt(300KB)
2.5 逐行解析
// 抽象组件:所有节点共同接口
class IFileSystemNode {
public:
virtual ~IFileSystemNode() {} // 虚析构
virtual size_t size() const = 0; // 计算大小
virtual void display(int depth = 0) const = 0; // 显示结构
};
// 叶子节点:文件
class File : public IFileSystemNode {
size_t size() const override {
return m_size; // 直接返回自身大小
}
void display(int depth = 0) const override {
std::string indent(depth * 2, '-');
std::cout << indent << m_name << " (" << m_size << " KB)" << std::endl;
}
};
// 组合节点:文件夹
class Folder : public IFileSystemNode {
std::vector<IFileSystemNode*> m_children; // 子节点列表
size_t size() const override {
size_t total = 0;
for (const auto& child : m_children) {
total += child->size(); // 递归累加所有子节点大小
}
return total;
}
void display(int depth = 0) const override {
// 先显示文件夹自身
std::cout << std::string(depth * 2, '-') << m_name << "/" << std::endl;
// 再递归显示所有子节点
for (const auto& child : m_children) {
child->display(depth + 1);
}
}
};
2.6 对比表
| 特性 |
透明组合模式 |
安全组合模式 |
| 接口定义 |
包含所有操作 |
仅包含共同操作 |
| 安全性 |
低,Leaf也可以add |
高,叶子节点无add |
| 透明性 |
高,一致性外露 |
低,需判断节点类型 |
2.7 面试追问 FAQ
| 问题 |
回答 |
| 组合模式与迭代器模式? |
组合模式构成树形结构,迭代器遍历树形结构 |
| 如何防止环状引用? |
在add时检查,避免子节点已包含父节点 |
| 组合模式优点? |
一致性接口,简化客户端代码 |
三、桥接模式(Bridge)
3.1 模式定义
将抽象部分与实现部分分离,使它们都可以独立地变化。
核心要点:
- 抽象部分包含实现部分的引用
- 两者可以独立扩展,不互相影响
- 避免类爆炸
3.2 结构
Abstraction(抽象)
|ref
Implementor(实现接口)
↑
|
ConcreteImplementor(具体实现)
3.3 代码实现
#include <iostream>
#include <string>
// 实现部分:消息发送接口
class IMessageSender {
public:
virtual ~IMessageSender() {}
virtual void send(const std::string& message) = 0;
};
// 具体实现:邮件发送
class EmailSender : public IMessageSender {
public:
void send(const std::string& message) override {
std::cout << "[Email] " << message << std::endl;
}
};
// 具体实现:短信发送
class SmsSender : public IMessageSender {
public:
void send(const std::string& message) override {
std::cout << "[SMS] " << message << std::endl;
}
};
// 具体实现:微信发送
class WechatSender : public IMessageSender {
public:
void send(const std::string& message) override {
std::cout << "[Wechat] " << message << std::endl;
}
};
// 抽象部分:消息
class Message {
protected:
IMessageSender* m_sender; // 桥接引用
public:
Message(IMessageSender* sender) : m_sender(sender) {}
virtual ~Message() {}
virtual void sendMessage(const std::string& content) = 0;
};
// 扩展抽象:普通消息
class NormalMessage : public Message {
public:
NormalMessage(IMessageSender* sender) : Message(sender) {}
void sendMessage(const std::string& content) override {
std::cout << "Normal: ";
m_sender->send(content);
}
};
// 扩展抽象:紧急消息
class UrgentMessage : public Message {
public:
UrgentMessage(IMessageSender* sender) : Message(sender) {}
void sendMessage(const std::string& content) override {
std::cout << "URGENT: ";
m_sender->send("[URGENT] " + content);
}
};
int main() {
// 普通消息用邮件发送
Message* m1 = new NormalMessage(new EmailSender());
m1->sendMessage("Hello");
// 紧急消息用短信发送
Message* m2 = new UrgentMessage(new SmsSender());
m2->sendMessage("Emergency!");
// 普通消息用微信发送
Message* m3 = new NormalMessage(new WechatSender());
m3->sendMessage("Hi");
delete m1; delete m2; delete m3;
return 0;
}
3.4 流程图
m1 = new NormalMessage(EmailSender)
|
v
m1.sendMessage("Hello")
|
v
输出: Normal: [Email] Hello
m2 = new UrgentMessage(SmsSender)
|
v
m2.sendMessage("Emergency!")
|
v
输出: URGENT: [SMS] [URGENT] Emergency!
m3 = new NormalMessage(WechatSender)
|
v
m3.sendMessage("Hi")
|
v
输出: Normal: [Wechat] Hi
3.5 逐行解析
// 实现接口:消息发送器
class IMessageSender {
public:
virtual ~IMessageSender() {}
virtual void send(const std::string& message) = 0; // 发送消息
};
// 抽象部分:消息(包含发送器引用)
class Message {
protected:
IMessageSender* m_sender; // 桥接指针
public:
Message(IMessageSender* sender) : m_sender(sender) {}
virtual void sendMessage(const std::string& content) = 0;
};
// 普通消息
class NormalMessage : public Message {
void sendMessage(const std::string& content) override {
std::cout << "Normal: ";
m_sender->send(content); // 委托给发送器
}
};
// 紧急消息
class UrgentMessage : public Message {
void sendMessage(const std::string& content) override {
std::cout << "URGENT: ";
m_sender->send("[URGENT] " + content); // 添加前缀后委托
}
};
3.6 对比表
| 模式 |
聚合方式 |
目的 |
| 桥接模式 |
组合(用指针) |
分离抽象和实现,独立变化 |
| 适配器模式 |
组合/继承 |
转换接口,使不兼容兼容 |
| 装饰器模式 |
组合 |
动态增加职责 |
3.7 面试追问 FAQ
| 问题 |
回答 |
| 桥接模式和继承的区别? |
继承是静态的,桥接是动态的;继承易类爆炸,桥接解耦 |
| 什么时候用桥接模式? |
抽象和实现都需要独立扩展时 |
| 桥接模式优点? |
减少类数量,提高可维护性 |
四、代理模式(Proxy)
4.1 模式定义
为其他对象提供一种代理以控制对这个对象的访问。
核心要点:
- 代理和真实对象实现相同接口
- 代理控制对真实对象的访问
- 客户端通过代理间接访问真实对象
4.2 结构
Client
|
v
Proxy(代理)
|
v
RealSubject(真实对象)
4.3 代码实现
#include <iostream>
#include <string>
// 抽象接口:图像
class IImage {
public:
virtual ~IImage() {}
virtual void display() = 0;
};
// 真实对象:大图片(加载慢)
class RealImage : public IImage {
private:
std::string m_filename;
public:
RealImage(const std::string& filename) : m_filename(filename) {
std::cout << "Loading image from disk: " << filename << std::endl;
}
void display() override {
std::cout << "Displaying: " << m_filename << std::endl;
}
};
// 代理:延迟加载
class ImageProxy : public IImage {
private:
std::string m_filename;
RealImage* m_realImage;
public:
ImageProxy(const std::string& filename)
: m_filename(filename), m_realImage(nullptr) {}
void display() override {
if (m_realImage == nullptr) {
std::cout << "[Proxy] First access, loading now..." << std::endl;
m_realImage = new RealImage(m_filename);
}
std::cout << "[Proxy] ";
m_realImage->display();
}
~ImageProxy() {
delete m_realImage;
}
};
int main() {
std::cout << "=== Creating proxies ===" << std::endl;
IImage* img1 = new ImageProxy("photo1.jpg");
IImage* img2 = new ImageProxy("photo2.jpg");
std::cout << "\n=== First display (triggers loading) ===" << std::endl;
img1->display();
img1->display(); // 第二次直接从缓存显示
std::cout << "\n=== Second display (from cache) ===" << std::endl;
img2->display();
delete img1; delete img2;
return 0;
}
4.4 流程图
第一次img1.display()
|
v
[Proxy检查m_realImage==nullptr]
|
v
[输出: Loading image from disk: photo1.jpg]
|
v
[输出: Displaying: photo1.jpg]
第二次img1.display()
|
v
[Proxy检查m_realImage!=nullptr]
|
v
[直接调用m_realImage->display()]
|
v
[输出: Displaying: photo1.jpg]
4.5 逐行解析
// 抽象接口
class IImage {
public:
virtual ~IImage() {}
virtual void display() = 0;
};
// 真实对象:实际加载图片
class RealImage : public IImage {
RealImage(const std::string& filename) {
// 模拟耗时操作
std::cout << "Loading image from disk: " << filename << std::endl;
}
void display() override {
std::cout << "Displaying: " << m_filename << std::endl;
}
};
// 代理:延迟加载
class ImageProxy : public IImage {
RealImage* m_realImage; // 懒加载,初始为nullptr
void display() override {
if (m_realImage == nullptr) {
std::cout << "[Proxy] First access, loading now..." << std::endl;
m_realImage = new RealImage(m_filename); // 第一次才加载
}
m_realImage->display(); // 委托
}
};
4.6 对比表
| 代理类型 |
用途 |
场景 |
| 远程代理 |
访问远程对象 |
WebService |
| 虚代理 |
延迟加载 |
大图片、文档 |
| 保护代理 |
权限控制 |
访问控制 |
| 智能引用 |
访问时额外操作 |
引用计数 |
4.7 面试追问 FAQ
| 问题 |
回答 |
| 代理和装饰器的区别? |
代理控制访问,装饰器增加功能 |
| 代理模式下 Subjects 是否实现同一接口? |
是,这是透明访问的基础 |
| 如何实现远程代理? |
序列化 + 网络传输 |
五、外观模式(Facade)
5.1 模式定义
为子系统中的一组接口提供一个统一的接口。外观模式定义了一个高级接口,使子系统更易于使用。
核心要点:
- 封装子系统的复杂接口
- 提供统一的简单接口
- 客户端与子系统解耦
5.2 结构
Client --Facade--> SubSystem1
SubSystem2
SubSystem3
5.3 代码实现
#include <iostream>
#include <string>
// 子系统1:CPU
class CPU {
public:
void start() { std::cout << "CPU: Starting..." << std::endl; }
void execute() { std::cout << "CPU: Executing instructions..." << std::endl; }
void stop() { std::cout << "CPU: Stopping..." << std::endl; }
};
// 子系统2:内存
class Memory {
public:
void load() { std::cout << "Memory: Loading data..." << std::endl; }
void clean() { std::cout << "Memory: Cleaning..." << std::endl; }
};
// 子系统3:硬盘
class HardDrive {
public:
void read() { std::cout << "HardDrive: Reading boot sector..." << std::endl; }
void write() { std::cout << "HardDrive: Writing data..." << std::endl; }
};
// 外观:电脑启动器
class ComputerFacade {
private:
CPU* m_cpu;
Memory* m_memory;
HardDrive* m_hardDrive;
public:
ComputerFacade() : m_cpu(new CPU()), m_memory(new Memory()), m_hardDrive(new HardDrive()) {}
~ComputerFacade() { delete m_cpu; delete m_memory; delete m_hardDrive; }
void start() {
std::cout << "=== Starting Computer ===" << std::endl;
m_hardDrive->read();
m_memory->load();
m_cpu->start();
m_cpu->execute();
std::cout << "=== Computer Started ===" << std::endl;
}
void shutdown() {
std::cout << "=== Shutting Down Computer ===" << std::endl;
m_cpu->stop();
m_memory->clean();
std::cout << "=== Computer Shutdown ===" << std::endl;
}
};
int main() {
ComputerFacade computer;
computer.start();
std::cout << std::endl;
computer.shutdown();
return 0;
}
5.4 流程图
computer.start()
|
v
[输出: === Starting Computer ===]
|
v
[HardDrive.read()]
|
v
[Memory.load()]
|
v
[CPU.start()]
|
v
[CPU.execute()]
|
v
[输出: === Computer Started ===]
5.5 逐行解析
// 外观类:封装子系统的复杂操作
class ComputerFacade {
private:
CPU* m_cpu;
Memory* m_memory;
HardDrive* m_hardDrive;
public:
// 启动电脑:一条命令代替多个子系统调用
void start() {
m_hardDrive->read(); // 读取引导扇区
m_memory->load(); // 加载数据到内存
m_cpu->start(); // 启动CPU
m_cpu->execute(); // 执行指令
}
// 关机
void shutdown() {
m_cpu->stop();
m_memory->clean();
}
};
// 客户端只需要调用外观即可
ComputerFacade computer;
computer.start(); // 一行代码启动电脑
5.6 对比表
| 模式 |
关注点 |
复杂度 |
| 外观模式 |
封装子系统,提供简单接口 |
简化客户端 |
| 中介者模式 |
封装对象间的交互 |
减少耦合 |
| 适配器模式 |
转换接口 |
使不兼容兼容 |
5.7 面试追问 FAQ
| 问题 |
回答 |
| 外观模式与迪米特法则? |
外观是迪米特法则的典型实现,减少依赖 |
| 外观模式能否调用子系统所有功能? |
是,但通常只封装常用操作 |
| 外观模式缺点? |
可能引入不必要的耦合 |
六、享元模式(Flyweight)
6.1 模式定义
运用共享技术有效地支持大量细粒度的对象。
核心要点:
- 分离内部状态(可共享)和外部状态(不可共享)
- 通过工厂缓存共享对象
- 大幅减少内存占用
6.2 结构
FlyweightFactory
|creates
|keeps
Flyweight <-- intrinsic state (shareable)
↑
|
ConcreteFlyweight
|extrinsic state (per-call passed)
Client
6.3 代码实现
#include <iostream>
#include <unordered_map>
#include <string>
// 享元接口:字符
class CharacterFlyweight {
public:
virtual ~CharacterFlyweight() {}
virtual void display(char extrinsicState) = 0; // 外部状态作为参数传入
};
// 具体享元:字符(内部状态:字形数据)
class Character : public CharacterFlyweight {
private:
char m_char; // 内部状态,所有相同字符共享
public:
Character(char c) : m_char(c) {
std::cout << " [Creating flyweight for: '" << c << "']" << std::endl;
}
void display(char fontSize) override {
std::cout << "Character '" << m_char << "' with font size " << fontSize << std::endl;
}
};
// 享元工厂
class CharacterFactory {
private:
std::unordered_map<char, CharacterFlyweight*> m_pool;
public:
CharacterFlyweight* getCharacter(char c) {
auto it = m_pool.find(c);
if (it == m_pool.end()) {
std::cout << "Creating new flyweight for: ";
CharacterFlyweight* flyweight = new Character(c);
m_pool[c] = flyweight;
return flyweight;
}
std::cout << "Reusing flyweight for: ";
return it->second;
}
};
int main() {
std::cout << "=== Document with many repeated characters ===" << std::endl;
CharacterFactory factory;
std::string text = "abracadabra";
for (char c : text) {
// 字符本身('a', 'b', 'r'...)是内部状态,可共享
// 字体大小是外部状态,每次调用不同
char fontSize = (c - 'a') + 12; // 不同位置字体不同
CharacterFlyweight* flyweight = factory.getCharacter(c);
flyweight->display(fontSize);
}
std::cout << "\nTotal unique characters: " << 5 << std::endl;
std::cout << "Total characters in text: " << text.length() << std::endl;
return 0;
}
6.4 流程图
遍历 "abracadabra"
|
v
'a': factory.getCharacter('a')
|--> 创建新的flyweight (存储在池中)
|--> display(font=12)
|
v
'b': factory.getCharacter('b')
|--> 创建新的flyweight
|--> display(font=13)
|
v
'r': factory.getCharacter('r')
|--> 创建新的flyweight
|--> display(font=18)
|
v
'a' again: factory.getCharacter('a')
|--> 复用已有flyweight
|--> display(font=12)
|
v
... (5个不同字符复用多次)
6.5 逐行解析
// 享元接口
class CharacterFlyweight {
public:
// 外部状态作为参数传入,不存储在享元中
virtual void display(char fontSize) = 0;
};
// 具体享元:内部状态(字符代码)存储在对象中
class Character : public CharacterFlyweight {
private:
char m_char; // 内部状态,所有'a'共享同一个对象
public:
Character(char c) : m_char(c) {
std::cout << " [Creating flyweight for: '" << c << "']" << std::endl;
}
void display(char fontSize) override {
// 内部状态 + 外部状态 = 完整信息
std::cout << "Character '" << m_char << "' with font size " << fontSize << std::endl;
}
};
// 工厂:管理享元池
class CharacterFactory {
std::unordered_map<char, CharacterFlyweight*> m_pool;
CharacterFlyweight* getCharacter(char c) {
if (m_pool.find(c) == m_pool.end()) {
m_pool[c] = new Character(c); // 不存在则创建
}
return m_pool[c]; // 存在则复用
}
};
6.6 对比表
| 优化方式 |
减少 |
适用场景 |
| 享元模式 |
对象数量 |
大量重复对象 |
| 对象池模式 |
分配开销 |
连接池、线程池 |
| 单例模式 |
对象数量 |
全局唯一 |
6.7 面试追问 FAQ
| 问题 |
回答 |
| 内部状态和外部状态? |
内部状态可共享,外部状态随场景变化 |
| 享元模式线程安全? |
工厂需要加锁保护池 |
| 何时用享元模式? |
对象数量大且可共享时,如文本编辑器字符 |
七、总结
7.1 模式对比总表
| 模式 |
结构类型 |
核心目的 |
关键词 |
| 装饰器 |
结构型 |
动态增加职责 |
包装、嵌套 |
| 组合 |
结构型 |
树形结构一致处理 |
递归、整体-部分 |
| 桥接 |
结构型 |
分离抽象与实现 |
解耦、独立变化 |
| 代理 |
结构型 |
控制对象访问 |
控制、延迟 |
| 外观 |
结构型 |
封装子系统复杂接口 |
简化、统一 |
| 享元 |
结构型 |
共享细粒度对象 |
内部状态、池化 |
7.2 设计模式分类速查
创建型(5个)
单例、工厂、抽象工厂、建造者、原型
结构型(7个)
代理、装饰、桥接、组合、外观、享元、适配器
行为型(11个)
策略、命令、职责链、状态、观察者、中介者、迭代器、模板方法、访问者、解释器、备忘录
7.3 选用指南
| 场景 |
推荐模式 |
| 希望动态给对象增加功能 |
装饰器 |
| 处理树形结构,一致性操作 |
组合 |
| 抽象和实现需要独立扩展 |
桥接 |
| 延迟加载大对象 |
代理 |
| 封装复杂子系统 |
外观 |
| 大量重复对象共享 |
享元 |
根据零声教育教学写作https://github.com/0voice