设计模式学习指南
什么是设计模式
设计模式是在软件设计中针对特定问题的可重用解决方案。它不是代码,而是解决问题的模板,可以在许多不同情况下使用。
设计模式的重要性
- 提高代码复用性:相同的设计可以在不同项目中使用
- 增强代码可读性:标准化的设计让代码更容易理解
- 降低维护成本:良好的设计降低后期维护难度
- 促进团队协作:统一的设计语言便于团队沟通
学习结构
1. 七大设计原则
- 单一职责原则 (Single Responsibility Principle)
- 开闭原则 (Open-Closed Principle)
- 里氏替换原则 (Liskov Substitution Principle)
- 接口隔离原则 (Interface Segregation Principle)
- 依赖倒置原则 (Dependency Inversion Principle)
- 迪米特法则 (Law of Demeter)
- 合成复用原则 (Composite Reuse Principle)
2. 二十三种设计模式
创建型模式 (5种)
- 单例模式 (Singleton)
- 工厂方法模式 (Factory Method)
- 抽象工厂模式 (Abstract Factory)
- 建造者模式 (Builder)
- 原型模式 (Prototype)
结构型模式 (7种)
- 适配器模式 (Adapter)
- 装饰器模式 (Decorator)
- 外观模式 (Facade)
- 组合模式 (Composite)
- 桥接模式 (Bridge)
- 享元模式 (Flyweight)
- 代理模式 (Proxy)
行为型模式 (11种)
- 观察者模式 (Observer)
- 策略模式 (Strategy)
- 命令模式 (Command)
- 状态模式 (State)
- 责任链模式 (Chain of Responsibility)
- 模板方法模式 (Template Method)
- 访问者模式 (Visitor)
- 中介者模式 (Mediator)
- 备忘录模式 (Memento)
- 迭代器模式 (Iterator)
- 解释器模式 (Interpreter)
学习建议
- 先理解原则,再学习模式
- 理论结合实践:每个模式都要写代码实现
- 关注应用场景:理解什么时候使用什么模式
- 避免过度设计:不要为了使用模式而使用模式
七大设计原则详解
1. 单一职责原则 (Single Responsibility Principle, SRP)
定义
一个类应该只有一个引起它变化的原因,即一个类只负责一项职责。
核心思想
- 降低类的复杂度
- 提高类的可读性和可维护性
- 降低变更引起的风险
示例
java
// 违反SRP的设计
class User {
private String name;
private String email;
public void setName(String name) { this.name = name; }
public void setEmail(String email) { this.email = email; }
// 用户数据验证 - 职责1
public boolean validateUser() { /* 验证逻辑 */ }
// 用户数据持久化 - 职责2
public void saveUser() { /* 保存逻辑 */ }
// 发送邮件 - 职责3
public void sendEmail() { /* 邮件逻辑 */ }
}
// 符合SRP的设计
class User {
private String name;
private String email;
// 只负责用户数据
}
class UserValidator {
public boolean validate(User user) { /* 验证逻辑 */ }
}
class UserRepository {
public void save(User user) { /* 保存逻辑 */ }
}
class EmailService {
public void sendEmail(User user) { /* 邮件逻辑 */ }
}
2. 开闭原则 (Open-Closed Principle, OCP)
定义
软件实体应该对扩展开放,对修改关闭。
核心思想
- 用抽象构建框架,用实现扩展细节
- 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化
- 而不是通过修改已有的代码来实现变化
示例
java
// 违反OCP的设计
class AreaCalculator {
public double calculateArea(Object shape) {
if (shape instanceof Rectangle) {
Rectangle rectangle = (Rectangle) shape;
return rectangle.length * rectangle.width;
} else if (shape instanceof Circle) {
Circle circle = (Circle) shape;
return Math.PI * circle.radius * circle.radius;
}
// 每次添加新形状都需要修改这个方法
return 0;
}
}
// 符合OCP的设计
abstract class Shape {
public abstract double calculateArea();
}
class Rectangle extends Shape {
private double length;
private double width;
@Override
public double calculateArea() {
return length * width;
}
}
class Circle extends Shape {
private double radius;
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
class AreaCalculator {
public double calculateArea(Shape shape) {
return shape.calculateArea(); // 无需修改,支持扩展
}
}
3. 里氏替换原则 (Liskov Substitution Principle, LSP)
定义
所有引用基类的地方必须能透明地使用其子类的对象。
核心思想
- 子类必须能够替换其基类
- 子类可以扩展父类的功能,但不能改变父类原有的功能
示例
java
// 违反LSP的设计
class Bird {
public void fly() {
System.out.println("鸟在飞");
}
}
class Penguin extends Bird {
@Override
public void fly() {
throw new UnsupportedOperationException("企鹅不会飞");
}
}
// 符合LSP的设计
abstract class Bird {
public abstract void move();
}
class FlyingBird extends Bird {
@Override
public void move() {
fly();
}
public void fly() {
System.out.println("鸟在飞");
}
}
class Penguin extends Bird {
@Override
public void move() {
swim();
}
public void swim() {
System.out.println("企鹅在游泳");
}
}
4. 接口隔离原则 (Interface Segregation Principle, ISP)
定义
客户端不应该依赖它不需要的接口。
核心思想
- 使用多个专门的接口,而不使用单一的总接口
- 接口应该小而专一
示例
java
// 违反ISP的设计
interface Worker {
void work();
void eat();
void sleep();
}
class HumanWorker implements Worker {
public void work() { /* 工作 */ }
public void eat() { /* 吃饭 */ }
public void sleep() { /* 睡觉 */ }
}
class RobotWorker implements Worker {
public void work() { /* 工作 */ }
public void eat() { throw new UnsupportedOperationException(); }
public void sleep() { throw new UnsupportedOperationException(); }
}
// 符合ISP的设计
interface Workable {
void work();
}
interface Eatable {
void eat();
}
interface Sleepable {
void sleep();
}
class HumanWorker implements Workable, Eatable, Sleepable {
public void work() { /* 工作 */ }
public void eat() { /* 吃饭 */ }
public void sleep() { /* 睡觉 */ }
}
class RobotWorker implements Workable {
public void work() { /* 工作 */ }
}
5. 依赖倒置原则 (Dependency Inversion Principle, DIP)
定义
- 高层模块不应该依赖低层模块,两者都应该依赖其抽象
- 抽象不应该依赖细节,细节应该依赖抽象
核心思想
- 面向接口编程,不要面向实现编程
- 通过抽象使各个类或模块的实现彼此独立
示例
java
// 违反DIP的设计
class MySQLDatabase {
public void save(String data) {
System.out.println("保存到MySQL数据库");
}
}
class UserService {
private MySQLDatabase database = new MySQLDatabase(); // 直接依赖具体实现
public void saveUser(String userData) {
database.save(userData);
}
}
// 符合DIP的设计
interface Database {
void save(String data);
}
class MySQLDatabase implements Database {
public void save(String data) {
System.out.println("保存到MySQL数据库");
}
}
class PostgreSQLDatabase implements Database {
public void save(String data) {
System.out.println("保存到PostgreSQL数据库");
}
}
class UserService {
private Database database; // 依赖抽象
public UserService(Database database) {
this.database = database;
}
public void saveUser(String userData) {
database.save(userData);
}
}
6. 迪米特法则 (Law of Demeter, LoD)
定义
一个对象应该对其他对象保持最少的了解,只与直接朋友通信。
核心思想
- 降低类之间的耦合度
- 提高模块的相对独立性
示例
java
// 违反迪米特法则
class Department {
private List<Employee> employees;
public List<Employee> getEmployees() {
return employees;
}
}
class Company {
private List<Department> departments;
public void printAllEmployees() {
for (Department dept : departments) {
for (Employee emp : dept.getEmployees()) { // 与Employee直接交互
System.out.println(emp.getName());
}
}
}
}
// 符合迪米特法则
class Department {
private List<Employee> employees;
public void printEmployees() { // 封装内部操作
for (Employee emp : employees) {
System.out.println(emp.getName());
}
}
}
class Company {
private List<Department> departments;
public void printAllEmployees() {
for (Department dept : departments) {
dept.printEmployees(); // 只与Department交互
}
}
}
7. 合成复用原则 (Composite Reuse Principle, CRP)
定义
尽量使用对象组合/聚合,而不是继承关系达到复用的目的。
核心思想
- 继承是白箱复用,组合是黑箱复用
- 组合的耦合度相对较低
示例
java
// 使用继承的设计
class Car {
public void start() { System.out.println("汽车启动"); }
public void stop() { System.out.println("汽车停止"); }
}
class SportsCar extends Car {
public void accelerate() { System.out.println("跑车加速"); }
}
// 使用组合的设计
class Engine {
public void start() { System.out.println("引擎启动"); }
public void stop() { System.out.println("引擎停止"); }
}
class Brake {
public void brake() { System.out.println("刹车"); }
}
class Car {
private Engine engine;
private Brake brake;
public Car() {
this.engine = new Engine();
this.brake = new Brake();
}
public void start() { engine.start(); }
public void stop() {
brake.brake();
engine.stop();
}
}
class SportsCar {
private Car car;
private Turbo turbo;
public SportsCar() {
this.car = new Car();
this.turbo = new Turbo();
}
public void start() { car.start(); }
public void stop() { car.stop(); }
public void accelerate() { turbo.boost(); }
}
总结
这七大设计原则是面向对象设计的基础,它们相互补充、相互促进:
- SRP 强调职责分离
- OCP 强调扩展性
- LSP 强调继承的正确性
- ISP 强调接口的专一性
- DIP 强调依赖抽象
- LoD 强调低耦合
- CRP 强调组合优于继承
遵循这些原则可以让我们的代码更加灵活、可维护、可扩展。
二十三种设计模式详解
创建型模式 (Creational Patterns)
创建型模式关注对象的创建过程,将对象的创建和使用分离。
1. 单例模式 (Singleton Pattern)
定义
确保一个类只有一个实例,并提供全局访问点。
应用场景
- 数据库连接池
- 线程池
- 缓存
- 日志对象
实现方式
java
// 饿汉式
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
// 懒汉式(线程安全)
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
2. 工厂方法模式 (Factory Method Pattern)
定义
定义一个创建对象的接口,让子类决定实例化哪一个类。
应用场景
- 创建复杂对象
- 框架代码需要创建对象但不知道具体类型
实现示例
java
// 产品接口
interface Product {
void use();
}
// 具体产品
class ConcreteProductA implements Product {
public void use() { System.out.println("使用产品A"); }
}
class ConcreteProductB implements Product {
public void use() { System.out.println("使用产品B"); }
}
// 工厂接口
abstract class Factory {
public abstract Product createProduct();
}
// 具体工厂
class ConcreteFactoryA extends Factory {
public Product createProduct() {
return new ConcreteProductA();
}
}
class ConcreteFactoryB extends Factory {
public Product createProduct() {
return new ConcreteProductB();
}
}
3. 抽象工厂模式 (Abstract Factory Pattern)
定义
提供一个创建一系列相关或相互依赖对象的接口。
应用场景
- 创建一系列相关的产品
- 跨平台开发
实现示例
java
// 抽象产品
interface Button {
void paint();
}
interface Checkbox {
void paint();
}
// 具体产品 - Windows
class WindowsButton implements Button {
public void paint() { System.out.println("Windows按钮"); }
}
class WindowsCheckbox implements Checkbox {
public void paint() { System.out.println("Windows复选框"); }
}
// 具体产品 - Mac
class MacButton implements Button {
public void paint() { System.out.println("Mac按钮"); }
}
class MacCheckbox implements Checkbox {
public void paint() { System.out.println("Mac复选框"); }
}
// 抽象工厂
interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
// 具体工厂
class WindowsFactory implements GUIFactory {
public Button createButton() { return new WindowsButton(); }
public Checkbox createCheckbox() { return new WindowsCheckbox(); }
}
class MacFactory implements GUIFactory {
public Button createButton() { return new MacButton(); }
public Checkbox createCheckbox() { return new MacCheckbox(); }
}
4. 建造者模式 (Builder Pattern)
定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
应用场景
- 创建复杂对象
- 对象的构造过程复杂且需要多个步骤
实现示例
java
class Computer {
private String cpu;
private String memory;
private String storage;
private String gpu;
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.memory = builder.memory;
this.storage = builder.storage;
this.gpu = builder.gpu;
}
public static class Builder {
private String cpu;
private String memory;
private String storage;
private String gpu;
public Builder setCpu(String cpu) {
this.cpu = cpu;
return this;
}
public Builder setMemory(String memory) {
this.memory = memory;
return this;
}
public Builder setStorage(String storage) {
this.storage = storage;
return this;
}
public Builder setGpu(String gpu) {
this.gpu = gpu;
return this;
}
public Computer build() {
return new Computer(this);
}
}
}
// 使用
Computer computer = new Computer.Builder()
.setCpu("Intel i7")
.setMemory("16GB")
.setStorage("512GB SSD")
.setGpu("RTX 3080")
.build();
5. 原型模式 (Prototype Pattern)
定义
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
应用场景
- 对象的创建非常复杂或耗时
- 需要创建大量相似对象
实现示例
java
class Sheep implements Cloneable {
private String name;
private int age;
public Sheep(String name, int age) {
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
// getters and setters
}
// 使用
Sheep originalSheep = new Sheep("多莉", 2);
Sheep clonedSheep = (Sheep) originalSheep.clone();
结构型模式 (Structural Patterns)
结构型模式关注类和对象的组合。
6. 适配器模式 (Adapter Pattern)
定义
将一个类的接口转换成客户希望的另一个接口,使原本不兼容的类可以合作。
应用场景
- 系统数据和行为都正确,但接口不符
- 想要使用已经存在的类,但其接口不符合需求
实现示例
java
// 目标接口
interface Target {
void request();
}
// 被适配的类
class Adaptee {
public void specificRequest() {
System.out.println("特殊请求");
}
}
// 适配器
class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest();
}
}
7. 装饰器模式 (Decorator Pattern)
定义
动态地给对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
应用场景
- 在不改变现有对象结构的情况下,动态地给对象增加功能
- Java I/O流
实现示例
java
// 组件接口
interface Component {
void operation();
}
// 具体组件
class ConcreteComponent implements Component {
@Override
public void operation() {
System.out.println("基本操作");
}
}
// 装饰器基类
abstract class Decorator implements Component {
protected Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
// 具体装饰器
class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
@Override
public void operation() {
super.operation();
addedBehavior();
}
private void addedBehavior() {
System.out.println("添加的行为A");
}
}
8. 外观模式 (Facade Pattern)
定义
为子系统中的一组接口提供一个一致的界面,定义一个高层接口,使子系统更容易使用。
应用场景
- 为复杂的子系统提供简单的接口
- 客户程序与多个子系统之间存在很大依赖性
实现示例
java
// 子系统类
class CPU {
public void start() { System.out.println("CPU启动"); }
public void shutdown() { System.out.println("CPU关闭"); }
}
class Memory {
public void start() { System.out.println("内存启动"); }
public void shutdown() { System.out.println("内存关闭"); }
}
class HardDrive {
public void start() { System.out.println("硬盘启动"); }
public void shutdown() { System.out.println("硬盘关闭"); }
}
// 外观类
class ComputerFacade {
private CPU cpu;
private Memory memory;
private HardDrive hardDrive;
public ComputerFacade() {
this.cpu = new CPU();
this.memory = new Memory();
this.hardDrive = new HardDrive();
}
public void startComputer() {
cpu.start();
memory.start();
hardDrive.start();
System.out.println("电脑启动完成");
}
public void shutdownComputer() {
hardDrive.shutdown();
memory.shutdown();
cpu.shutdown();
System.out.println("电脑关闭完成");
}
}
9. 组合模式 (Composite Pattern)
定义
将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
应用场景
- 树形结构
- 文件系统
- 组织架构
实现示例
java
// 组件接口
abstract class Component {
protected String name;
public Component(String name) {
this.name = name;
}
public abstract void operation();
public abstract void add(Component component);
public abstract void remove(Component component);
}
// 叶子节点
class Leaf extends Component {
public Leaf(String name) {
super(name);
}
@Override
public void operation() {
System.out.println("叶子节点: " + name);
}
@Override
public void add(Component component) {
throw new UnsupportedOperationException();
}
@Override
public void remove(Component component) {
throw new UnsupportedOperationException();
}
}
// 组合节点
class Composite extends Component {
private List<Component> children = new ArrayList<>();
public Composite(String name) {
super(name);
}
@Override
public void operation() {
System.out.println("组合节点: " + name);
for (Component child : children) {
child.operation();
}
}
@Override
public void add(Component component) {
children.add(component);
}
@Override
public void remove(Component component) {
children.remove(component);
}
}
10. 桥接模式 (Bridge Pattern)
定义
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
应用场景
- 避免抽象和实现之间的永久绑定
- 抽象和实现都可以通过继承独立扩展
实现示例
java
// 实现接口
interface DrawAPI {
void drawCircle(int radius, int x, int y);
}
// 具体实现
class RedCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: red, radius: " + radius + ", x: " + x + ", " + y + "]");
}
}
class GreenCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: green, radius: " + radius + ", x: " + x + ", " + y + "]");
}
}
// 抽象类
abstract class Shape {
protected DrawAPI drawAPI;
protected Shape(DrawAPI drawAPI) {
this.drawAPI = drawAPI;
}
public abstract void draw();
}
// 具体抽象类
class Circle extends Shape {
private int x, y, radius;
public Circle(int x, int y, int radius, DrawAPI drawAPI) {
super(drawAPI);
this.x = x;
this.y = y;
this.radius = radius;
}
public void draw() {
drawAPI.drawCircle(radius, x, y);
}
}
11. 享元模式 (Flyweight Pattern)
定义
运用共享技术有效地支持大量细粒度的对象。
应用场景
- 系统中有大量对象
- 这些对象消耗大量内存
- 对象的大部分状态都可以外部化
实现示例
java
// 享元接口
interface Flyweight {
void operation(String extrinsicState);
}
// 具体享元
class ConcreteFlyweight implements Flyweight {
private String intrinsicState;
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void operation(String extrinsicState) {
System.out.println("内部状态: " + intrinsicState + ", 外部状态: " + extrinsicState);
}
}
// 享元工厂
class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String key) {
if (!flyweights.containsKey(key)) {
flyweights.put(key, new ConcreteFlyweight(key));
}
return flyweights.get(key);
}
public int getSize() {
return flyweights.size();
}
}
12. 代理模式 (Proxy Pattern)
定义
为其他对象提供一种代理以控制对这个对象的访问。
应用场景
- 远程代理
- 虚拟代理
- 保护代理
- 智能引用
实现示例
java
// 主题接口
interface Subject {
void request();
}
// 真实主题
class RealSubject implements Subject {
@Override
public void request() {
System.out.println("真实主题的请求");
}
}
// 代理
class Proxy implements Subject {
private RealSubject realSubject;
@Override
public void request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
preRequest();
realSubject.request();
postRequest();
}
private void preRequest() {
System.out.println("请求前的处理");
}
private void postRequest() {
System.out.println("请求后的处理");
}
}
行为型模式 (Behavioral Patterns)
行为型模式关注对象之间的通信和职责分配。
13. 观察者模式 (Observer Pattern)
定义
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
应用场景
- MVC架构
- 事件处理
- 发布-订阅系统
实现示例
java
// 观察者接口
interface Observer {
void update(String message);
}
// 主题接口
interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObservers();
}
// 具体主题
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state);
}
}
public void setState(String state) {
this.state = state;
notifyObservers();
}
}
// 具体观察者
class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " 收到消息: " + message);
}
}
14. 策略模式 (Strategy Pattern)
定义
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。
应用场景
- 多种算法实现同一功能
- 算法需要在运行时切换
实现示例
java
// 策略接口
interface Strategy {
int doOperation(int num1, int num2);
}
// 具体策略
class OperationAdd implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
class OperationSubtract implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
class OperationMultiply implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
// 上下文
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
15. 命令模式 (Command Pattern)
定义
将一个请求封装成一个对象,从而使你可用不同的请求对客户进行参数化。
应用场景
- 队列请求
- 记录日志
- 支持撤销操作
实现示例
java
// 命令接口
interface Command {
void execute();
void undo();
}
// 接收者
class Light {
public void on() {
System.out.println("灯开了");
}
public void off() {
System.out.println("灯关了");
}
}
// 具体命令
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
class LightOffCommand implements Command {
private Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
@Override
public void undo() {
light.on();
}
}
// 调用者
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndo() {
command.undo();
}
}
16. 状态模式 (State Pattern)
定义
允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
应用场景
- 对象的行为依赖于它的状态
- 状态转换逻辑复杂
实现示例
java
// 状态接口
interface State {
void handle(Context context);
}
// 具体状态
class ConcreteStateA implements State {
@Override
public void handle(Context context) {
System.out.println("处理状态A");
context.setState(new ConcreteStateB());
}
}
class ConcreteStateB implements State {
@Override
public void handle(Context context) {
System.out.println("处理状态B");
context.setState(new ConcreteStateA());
}
}
// 上下文
class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}
17. 责任链模式 (Chain of Responsibility Pattern)
定义
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
应用场景
- 有多个对象可以处理请求
- 不希望指定具体的处理者
实现示例
java
// 处理者抽象类
abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handleRequest(int request);
}
// 具体处理者
class ConcreteHandler1 extends Handler {
@Override
public void handleRequest(int request) {
if (request >= 0 && request < 10) {
System.out.println("ConcreteHandler1 处理请求 " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
class ConcreteHandler2 extends Handler {
@Override
public void handleRequest(int request) {
if (request >= 10 && request < 20) {
System.out.println("ConcreteHandler2 处理请求 " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
class ConcreteHandler3 extends Handler {
@Override
public void handleRequest(int request) {
if (request >= 20 && request < 30) {
System.out.println("ConcreteHandler3 处理请求 " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
18. 模板方法模式 (Template Method Pattern)
定义
定义一个操作中的算法骨架,而将一些步骤延迟到子类中。
应用场景
- 一次性实现一个算法的不变的部分
- 各子类中公共的行为应被提取出来并集中到一个公共父类中
实现示例
java
// 抽象类
abstract class AbstractClass {
// 模板方法
public final void templateMethod() {
primitiveOperation1();
primitiveOperation2();
concreteOperation();
hook();
}
protected abstract void primitiveOperation1();
protected abstract void primitiveOperation2();
private void concreteOperation() {
System.out.println("具体操作");
}
protected void hook() {
// 钩子方法,子类可以选择性重写
}
}
// 具体类
class ConcreteClass extends AbstractClass {
@Override
protected void primitiveOperation1() {
System.out.println("具体类的操作1");
}
@Override
protected void primitiveOperation2() {
System.out.println("具体类的操作2");
}
@Override
protected void hook() {
System.out.println("重写的钩子方法");
}
}
19. 访问者模式 (Visitor Pattern)
定义
表示一个作用于某对象结构中的各元素的操作,使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
应用场景
- 对象结构相对稳定,但经常需要在此对象结构上定义新的操作
实现示例
java
// 访问者接口
interface Visitor {
void visit(ConcreteElementA element);
void visit(ConcreteElementB element);
}
// 元素接口
interface Element {
void accept(Visitor visitor);
}
// 具体元素
class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String operationA() {
return "ConcreteElementA";
}
}
class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
public String operationB() {
return "ConcreteElementB";
}
}
// 具体访问者
class ConcreteVisitor implements Visitor {
@Override
public void visit(ConcreteElementA element) {
System.out.println("访问 " + element.operationA());
}
@Override
public void visit(ConcreteElementB element) {
System.out.println("访问 " + element.operationB());
}
}
20. 中介者模式 (Mediator Pattern)
定义
用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
应用场景
- 对象之间的交互比较复杂
- 对象之间的依赖关系混乱
实现示例
java
// 中介者接口
interface Mediator {
void send(String message, Colleague colleague);
}
// 同事类
abstract class Colleague {
protected Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
}
// 具体同事类
class ConcreteColleague1 extends Colleague {
public ConcreteColleague1(Mediator mediator) {
super(mediator);
}
public void send(String message) {
mediator.send(message, this);
}
public void notify(String message) {
System.out.println("同事1得到消息:" + message);
}
}
class ConcreteColleague2 extends Colleague {
public ConcreteColleague2(Mediator mediator) {
super(mediator);
}
public void send(String message) {
mediator.send(message, this);
}
public void notify(String message) {
System.out.println("同事2得到消息:" + message);
}
}
// 具体中介者
class ConcreteMediator implements Mediator {
private ConcreteColleague1 colleague1;
private ConcreteColleague2 colleague2;
public void setColleague1(ConcreteColleague1 colleague1) {
this.colleague1 = colleague1;
}
public void setColleague2(ConcreteColleague2 colleague2) {
this.colleague2 = colleague2;
}
@Override
public void send(String message, Colleague colleague) {
if (colleague == colleague1) {
colleague2.notify(message);
} else {
colleague1.notify(message);
}
}
}
21. 备忘录模式 (Memento Pattern)
定义
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
应用场景
- 需要保存/恢复数据的相关状态场景
- 提供一个可回滚的操作
实现示例
java
// 备忘录
class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 发起人
class Originator {
private String state;
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
// 管理者
class CareTaker {
private List<Memento> mementoList = new ArrayList<>();
public void add(Memento state) {
mementoList.add(state);
}
public Memento get(int index) {
return mementoList.get(index);
}
}
22. 迭代器模式 (Iterator Pattern)
定义
提供一种方法顺序访问一个聚合对象中各个元素,而又无须暴露该对象的内部表示。
应用场景
- 访问一个聚合对象的内容而无须暴露它的内部表示
- 需要为聚合对象提供多种遍历方式
实现示例
java
// 迭代器接口
interface Iterator<T> {
boolean hasNext();
T next();
}
// 聚合接口
interface Container<T> {
Iterator<T> getIterator();
}
// 具体迭代器
class NameIterator implements Iterator<String> {
private String[] names;
private int index;
public NameIterator(String[] names) {
this.names = names;
}
@Override
public boolean hasNext() {
return index < names.length;
}
@Override
public String next() {
if (hasNext()) {
return names[index++];
}
return null;
}
}
// 具体聚合
class NameRepository implements Container<String> {
private String[] names = {"Robert", "John", "Julie", "Lora"};
@Override
public Iterator<String> getIterator() {
return new NameIterator(names);
}
}
23. 解释器模式 (Interpreter Pattern)
定义
给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
应用场景
- 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树
- 一些重复出现的问题可以用一种简单的语言来进行表达
实现示例
java
// 抽象表达式
interface Expression {
boolean interpret(String context);
}
// 终结符表达式
class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data) {
this.data = data;
}
@Override
public boolean interpret(String context) {
return context.contains(data);
}
}
// 非终结符表达式
class OrExpression implements Expression {
private Expression expr1;
private Expression expr2;
public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}
class AndExpression implements Expression {
private Expression expr1;
private Expression expr2;
public AndExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) && expr2.interpret(context);
}
}
设计模式总结
创建型模式总结
- 单例模式:确保唯一实例
- 工厂方法模式:创建对象的接口
- 抽象工厂模式:创建相关对象族
- 建造者模式:构建复杂对象
- 原型模式:通过复制创建对象
结构型模式总结
- 适配器模式:接口转换
- 装饰器模式:动态添加功能
- 外观模式:简化接口
- 组合模式:树形结构
- 桥接模式:分离抽象和实现
- 享元模式:共享对象
- 代理模式:控制访问
行为型模式总结
- 观察者模式:一对多依赖
- 策略模式:算法族
- 命令模式:请求封装
- 状态模式:状态改变行为
- 责任链模式:请求传递
- 模板方法模式:算法框架
- 访问者模式:操作与对象分离
- 中介者模式:对象间通信
- 备忘录模式:状态保存
- 迭代器模式:顺序访问
- 解释器模式:语言解释
使用原则
- 优先使用组合而非继承
- 针对接口编程,而非实现
- 找出应用中可能需要变化之处,把它们独立出来
- 为了交互对象之间的松耦合设计而努力
设计模式深度分析:区别与异同
创建型模式对比分析
1. 工厂模式家族对比
工厂模式对比表
┌─────────────────┬─────────────────┬─────────────────┬─────────────────┐
│ 特性 │ 简单工厂 │ 工厂方法 │ 抽象工厂 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 创建对象数量 │ 单一产品 │ 单一产品 │ 产品族 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 扩展性 │ 差(需修改代码) │ 好(新增子类) │ 好(新增工厂) │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 符合开闭原则 │ ❌ 否 │ ✅ 是 │ ✅ 是 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 复杂度 │ 低 │ 中等 │ 高 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 使用场景 │ 产品类型固定 │ 单一产品多变化 │ 多产品协同工作 │
└─────────────────┴─────────────────┴─────────────────┴─────────────────┘
java
// 对比示例:创建数据库连接
// 简单工厂
class ConnectionFactory {
public static Connection createConnection(String type) {
if ("MySQL".equals(type)) return new MySQLConnection();
if ("Oracle".equals(type)) return new OracleConnection();
return null; // 新增类型需要修改这里
}
}
// 工厂方法
abstract class ConnectionFactory {
public abstract Connection createConnection();
}
class MySQLConnectionFactory extends ConnectionFactory {
public Connection createConnection() { return new MySQLConnection(); }
}
// 抽象工厂
interface DatabaseFactory {
Connection createConnection();
Command createCommand();
Transaction createTransaction();
}
class MySQLFactory implements DatabaseFactory {
public Connection createConnection() { return new MySQLConnection(); }
public Command createCommand() { return new MySQLCommand(); }
public Transaction createTransaction() { return new MySQLTransaction(); }
}
2. 单例 vs 建造者模式
单例模式 vs 建造者模式
┌─────────────────┬─────────────────┬─────────────────────────────┐
│ 特性 │ 单例模式 │ 建造者模式 │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ 实例数量 │ 全局唯一 │ 每次构建新实例 │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ 构造复杂度 │ 简单 │ 复杂,分步构造 │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ 参数化 │ 无参数化 │ 高度参数化 │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ 线程安全 │ 需要考虑 │ 通常不需要 │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ 使用目的 │ 控制实例数量 │ 复杂对象的创建过程 │
└─────────────────┴─────────────────┴─────────────────────────────┘
结构型模式对比分析
3. 装饰器 vs 代理 vs 适配器
结构型模式功能对比
┌─────────────────┬─────────────────┬─────────────────┬─────────────────┐
│ 模式 │ 装饰器 │ 代理 │ 适配器 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 主要目的 │ 增强功能 │ 控制访问 │ 接口转换 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 对象关系 │ 装饰-被装饰 │ 代理-目标 │ 适配器-适配者 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 接口兼容性 │ 相同接口 │ 相同接口 │ 不同接口 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 功能改变 │ 增加功能 │ 不改变功能 │ 转换接口 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 组合性 │ 可多层装饰 │ 通常单层 │ 通常单层 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 典型应用 │ Java I/O流 │ Spring AOP │ 第三方库集成 │
└─────────────────┴─────────────────┴─────────────────┴─────────────────┘
java
// 对比示例:文件操作
// 装饰器模式 - 增强功能
interface FileProcessor {
void process(String content);
}
class BasicFileProcessor implements FileProcessor {
public void process(String content) {
System.out.println("处理文件: " + content);
}
}
class EncryptionDecorator implements FileProcessor {
private FileProcessor processor;
public EncryptionDecorator(FileProcessor processor) {
this.processor = processor;
}
public void process(String content) {
String encrypted = encrypt(content);
processor.process(encrypted); // 增强:加密
}
}
// 代理模式 - 控制访问
class FileProcessorProxy implements FileProcessor {
private FileProcessor processor;
private boolean hasPermission;
public void process(String content) {
if (checkPermission()) { // 控制:权限检查
if (processor == null) {
processor = new BasicFileProcessor();
}
processor.process(content);
}
}
}
// 适配器模式 - 接口转换
class LegacyFileHandler {
public void handleFile(byte[] data) { /* 老接口 */ }
}
class FileHandlerAdapter implements FileProcessor {
private LegacyFileHandler handler;
public void process(String content) {
byte[] data = content.getBytes(); // 转换接口
handler.handleFile(data);
}
}
4. 组合 vs 装饰器模式
java
// 组合模式 - 处理树形结构
abstract class Component {
public abstract void operation();
public void add(Component component) { /* 默认实现 */ }
public void remove(Component component) { /* 默认实现 */ }
}
class Leaf extends Component {
public void operation() { System.out.println("叶子操作"); }
}
class Composite extends Component {
private List<Component> children = new ArrayList<>();
public void operation() {
System.out.println("组合操作");
for (Component child : children) {
child.operation(); // 递归处理子组件
}
}
public void add(Component component) { children.add(component); }
}
// 装饰器模式 - 动态添加功能
class ScrollbarDecorator extends ComponentDecorator {
public ScrollbarDecorator(VisualComponent component) {
super(component);
}
public void draw() {
super.draw();
drawScrollbar(); // 添加滚动条功能
}
}
// 关键区别:
// 组合模式:一对多的递归结构,处理整体-部分关系
// 装饰器模式:一对一的链式结构,动态添加功能
行为型模式对比分析
5. 策略 vs 状态 vs 命令模式
行为型模式功能对比
┌─────────────────┬─────────────────┬─────────────────┬─────────────────┐
│ 模式 │ 策略 │ 状态 │ 命令 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 核心思想 │ 算法封装 │ 状态转换 │ 请求封装 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 对象生命周期 │ 相对独立 │ 有状态转换 │ 可存储/重放 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 对象间关系 │ 平等的算法 │ 有序的状态 │ 发送者-接收者 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 主要解决问题 │ 算法选择 │ 状态管理 │ 操作解耦 │
├─────────────────┼─────────────────┼─────────────────┼─────────────────┤
│ 典型应用 │ 排序算法 │ 状态机 │ GUI按钮 │
└─────────────────┴─────────────────┴─────────────────┴─────────────────┘
java
// 对比示例:音乐播放器
// 策略模式 - 不同的播放算法
interface PlayStrategy {
void play(String song);
}
class NormalPlayStrategy implements PlayStrategy {
public void play(String song) { System.out.println("正常播放: " + song); }
}
class ShufflePlayStrategy implements PlayStrategy {
public void play(String song) { System.out.println("随机播放: " + song); }
}
class MusicPlayer {
private PlayStrategy strategy;
public void setPlayStrategy(PlayStrategy strategy) {
this.strategy = strategy; // 切换算法
}
public void play(String song) {
strategy.play(song);
}
}
// 状态模式 - 播放器状态管理
interface PlayerState {
void play(MusicPlayer player);
void pause(MusicPlayer player);
void stop(MusicPlayer player);
}
class PlayingState implements PlayerState {
public void play(MusicPlayer player) {
System.out.println("已在播放中");
}
public void pause(MusicPlayer player) {
System.out.println("暂停播放");
player.setState(new PausedState()); // 状态转换
}
public void stop(MusicPlayer player) {
System.out.println("停止播放");
player.setState(new StoppedState());
}
}
// 命令模式 - 播放操作封装
interface Command {
void execute();
void undo();
}
class PlayCommand implements Command {
private MusicPlayer player;
private String song;
public PlayCommand(MusicPlayer player, String song) {
this.player = player;
this.song = song;
}
public void execute() {
player.play(song); // 封装操作
}
public void undo() {
player.stop(); // 可撤销
}
}
6. 观察者 vs 中介者模式
java
// 观察者模式 - 一对多通知
class Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
public void attach(Observer observer) {
observers.add(observer);
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(state); // 直接通知
}
}
}
// 中介者模式 - 多对多协调
class ChatMediator {
private List<User> users = new ArrayList<>();
public void sendMessage(String message, User sender) {
for (User user : users) {
if (user != sender) {
user.receive(message); // 中介转发
}
}
}
}
// 关键区别:
// 观察者:一个主题对多个观察者,单向依赖
// 中介者:多个对象通过中介者通信,降低耦合
模式组合与演化
7. 常见模式组合
java
// 工厂 + 单例:确保工厂唯一性
class DatabaseConnectionFactory {
private static DatabaseConnectionFactory instance;
private DatabaseConnectionFactory() {}
public static DatabaseConnectionFactory getInstance() {
if (instance == null) {
synchronized (DatabaseConnectionFactory.class) {
if (instance == null) {
instance = new DatabaseConnectionFactory();
}
}
}
return instance;
}
public Connection createConnection(String type) {
// 工厂方法
}
}
// 装饰器 + 策略:动态功能 + 算法选择
class ProcessorDecorator implements DataProcessor {
private DataProcessor processor;
private CompressionStrategy strategy; // 策略模式
public ProcessorDecorator(DataProcessor processor, CompressionStrategy strategy) {
this.processor = processor;
this.strategy = strategy;
}
public void process(Data data) {
Data compressed = strategy.compress(data); // 策略压缩
processor.process(compressed); // 装饰器转发
}
}
// 观察者 + 命令:事件驱动 + 操作封装
class EventDrivenSystem {
private List<EventObserver> observers = new ArrayList<>();
private Queue<Command> commandQueue = new LinkedList<>();
public void notifyEvent(Event event) {
for (EventObserver observer : observers) {
Command cmd = observer.createCommand(event); // 观察者创建命令
commandQueue.offer(cmd); // 命令排队
}
// 异步执行命令
while (!commandQueue.isEmpty()) {
commandQueue.poll().execute();
}
}
}
模式选择指南
8. 问题导向的模式选择
模式选择决策树
┌─────────────────────────────────────────────────────────────┐
│ 需要解决什么问题? │
│ │
│ 创建对象复杂?────┬─── 是 ─── 工厂模式家族 │
│ │ 建造者模式 │
│ │ 原型模式 │
│ │ │
│ └─── 否 ─── 继续分析... │
│ │
│ 需要统一接口?────┬─── 接口不兼容 ─── 适配器模式 │
│ │ │
│ ├─── 简化复杂接口 ─── 外观模式 │
│ │ │
│ └─── 动态添加功能 ─── 装饰器模式 │
│ │
│ 对象间通信复杂?──┬─── 一对多通知 ─── 观察者模式 │
│ │ │
│ ├─── 多对多协调 ─── 中介者模式 │
│ │ │
│ └─── 算法变化 ─── 策略模式 │
│ │
│ 需要撤销操作?─────── 命令模式 │
│ │
│ 状态转换复杂?─────── 状态模式 │
│ │
│ 树形结构处理?─────── 组合模式 │
└─────────────────────────────────────────────────────────────┘
9. 模式误用分析
java
// 反模式示例:过度使用设计模式
// 错误:为简单功能使用复杂模式
class SimpleCalculatorFactory { // 不必要的工厂
public static Calculator createCalculator() {
return new Calculator();
}
}
// 正确:直接使用
Calculator calc = new Calculator();
// 错误:强行使用单例
class MathUtilsSingleton {
private static MathUtilsSingleton instance;
public static MathUtilsSingleton getInstance() { return instance; }
public int add(int a, int b) { return a + b; } // 无状态方法
}
// 正确:使用静态方法
class MathUtils {
public static int add(int a, int b) { return a + b; }
}
// 错误:不必要的观察者模式
class SimpleNotifier {
private List<Observer> observers = new ArrayList<>();
public void notify(String message) {
// 如果只有一个固定的观察者,直接调用即可
for (Observer obs : observers) {
obs.update(message);
}
}
}
// 正确:直接调用
class SimpleNotifier {
private Logger logger;
public void notify(String message) {
logger.log(message); // 直接调用
}
}
设计模式与架构原则的关系
10. 模式与SOLID原则映射
设计模式与SOLID原则关系
┌─────────────────┬─────────────────┬─────────────────────────────┐
│ SOLID原则 │ 支持的模式 │ 关系说明 │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ 单一职责原则 │ 装饰器、策略、 │ 每个类只负责一个变化原因 │
│ (SRP) │ 命令、观察者 │ │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ 开闭原则 │ 工厂方法、抽象 │ 对扩展开放,对修改关闭 │
│ (OCP) │ 工厂、策略、 │ │
│ │ 观察者、装饰器 │ │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ 里氏替换原则 │ 所有使用继承 │ 子类可以替换父类 │
│ (LSP) │ 的模式 │ │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ 接口隔离原则 │ 适配器、外观、 │ 客户端不依赖不需要的接口 │
│ (ISP) │ 桥接 │ │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ 依赖倒置原则 │ 工厂系列、抽象 │ 依赖抽象而不是具体实现 │
│ (DIP) │ 工厂、策略 │ │
└─────────────────┴─────────────────┴─────────────────────────────┘
实际应用中的模式演化
11. 模式在不同阶段的应用
java
// 项目演化过程中的模式使用
// 阶段1:简单直接的实现
class OrderService {
public void processOrder(Order order) {
// 验证订单
if (order.getAmount() <= 0) {
throw new IllegalArgumentException("Invalid amount");
}
// 计算价格
double total = order.getAmount() * order.getPrice();
if (order.isVip()) {
total *= 0.9; // VIP折扣
}
// 发送通知
System.out.println("发送邮件通知");
System.out.println("发送短信通知");
// 保存订单
System.out.println("保存到数据库");
}
}
// 阶段2:应用策略模式重构定价逻辑
interface PricingStrategy {
double calculatePrice(Order order);
}
class VipPricingStrategy implements PricingStrategy {
public double calculatePrice(Order order) {
return order.getAmount() * order.getPrice() * 0.9;
}
}
class RegularPricingStrategy implements PricingStrategy {
public double calculatePrice(Order order) {
return order.getAmount() * order.getPrice();
}
}
// 阶段3:应用观察者模式解耦通知
interface OrderObserver {
void onOrderProcessed(Order order);
}
class EmailNotifier implements OrderObserver {
public void onOrderProcessed(Order order) {
System.out.println("发送邮件通知");
}
}
class SmsNotifier implements OrderObserver {
public void onOrderProcessed(Order order) {
System.out.println("发送短信通知");
}
}
// 阶段4:应用命令模式支持撤销
interface Command {
void execute();
void undo();
}
class ProcessOrderCommand implements Command {
private Order order;
private OrderService service;
private boolean executed = false;
public void execute() {
if (!executed) {
service.processOrder(order);
executed = true;
}
}
public void undo() {
if (executed) {
service.cancelOrder(order);
executed = false;
}
}
}
// 最终重构后的服务
class OrderService {
private List<OrderObserver> observers = new ArrayList<>();
private PricingStrategy pricingStrategy;
public void processOrder(Order order) {
// 验证
validateOrder(order);
// 计算价格 - 策略模式
double total = pricingStrategy.calculatePrice(order);
order.setTotal(total);
// 保存订单
saveOrder(order);
// 通知观察者 - 观察者模式
notifyObservers(order);
}
// 支持命令模式的接口
public Command createProcessCommand(Order order) {
return new ProcessOrderCommand(order, this);
}
}
总结:模式选择的核心原则
- 问题导向:先识别问题,再选择模式
- 简单优先:能用简单方案解决的不用复杂模式
- 组合使用:复杂场景往往需要多种模式配合
- 演化思维:模式是重构的结果,不是设计的起点
- 权衡取舍:每种模式都有代价,需要权衡利弊
设计模式成熟度模型
模式应用成熟度
┌─────────────────┬─────────────────┬─────────────────────────────┐
│ 成熟度等级 │ 特征描述 │ 典型表现 │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ Level 1: 认知 │ 了解模式概念 │ 能说出23种模式名称 │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ Level 2: 理解 │ 掌握模式结构 │ 能画出UML图,实现示例代码 │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ Level 3: 应用 │ 识别使用场景 │ 能在项目中正确应用模式 │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ Level 4: 综合 │ 模式组合使用 │ 能组合多种模式解决复杂问题 │
├─────────────────┼─────────────────┼─────────────────────────────┤
│ Level 5: 创新 │ 模式演化创新 │ 能根据需要调整或创新模式 │
└─────────────────┴─────────────────┴─────────────────────────────┘
通过深入理解各模式间的区别与联系,我们能够更好地在实际项目中选择和应用适当的设计模式,写出更加优雅、可维护的代码。
STL中的设计模式应用
C++标准模板库(STL)是一个强大的工具,它提供了一系列通用类和函数的集合,旨在促进代码的重用和效率。在STL中,设计模式的应用使得这些组件更加灵活和高效。以下是STL中设计模式应用的深入分析,包括序列容器、关联容器、容器适配器以及算法等方面。
1. STL中的设计模式概述
STL中的设计模式主要体现在以下几个方面:
- 迭代器模式:提供统一的接口访问不同容器的元素。
- 策略模式:算法可以独立于使用它们的客户端而变化。
- 命令模式:将请求封装为对象,以便于参数化和队列处理。
- 享元模式:通过共享技术有效地支持大量细粒度的对象。
- 代理模式:为其他对象提供一种代理以控制对这个对象的访问。
这些模式的应用大大提高了STL的灵活性和可扩展性,使得开发者可以更加专注于业务逻辑而非底层细节。
2. STL设计模式应用实例
2.1 序列容器
cpp
// vector - 动态数组
#include <vector>
std::vector<int> vec = {1, 2, 3, 4, 5};
vec.push_back(6); // 尾部插入
vec.pop_back(); // 尾部删除
int val = vec[0]; // 随机访问 O(1)
vec.insert(vec.begin(), 0); // 任意位置插入 O(n)
// deque - 双端队列
#include <deque>
std::deque<int> deq = {2, 3, 4};
deq.push_front(1); // 头部插入 O(1)
deq.push_back(5); // 尾部插入 O(1)
deq.pop_front(); // 头部删除 O(1)
// list - 双向链表
#include <list>
std::list<int> lst = {1, 3, 5};
lst.push_front(0); // 头部插入 O(1)
lst.insert(lst.begin(), 2); // 任意位置插入 O(1)
lst.sort(); // 排序 O(n log n)
设计模式在STL中的应用对比
STL设计模式应用架构图
┌─────────────────────────────────────────────────────────────┐
│ 迭代器模式应用 │
│ │
│ ┌─────────────┐ 统一接口 ┌─────────────────────────┐ │
│ │ 容器 │◀──────────────│ 迭代器 │ │
│ │ vector │ │ vector::iterator │ │
│ │ list │ │ list::iterator │ │
│ │ deque │ │ deque::iterator │ │
│ └─────────────┘ └─────────────────────────┘ │
│ ▲ ▲ │
│ │ │ │
│ 隐藏实现 提供统一访问 │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ 内部数据 │ │ 算法函数 │ │
│ │ 结构 │ │ std::sort() │ │
│ │ │ │ std::find() │ │
│ └─────────────┘ └─────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 策略模式应用 │
│ │
│ ┌─────────────┐ 使用策略 ┌─────────────────────────┐ │
│ │ 算法 │◀──────────────│ 比较策略 │ │
│ │ std::sort │ │ std::less<T> │ │
│ │ std::find │ │ std::greater<T> │ │
│ └─────────────┘ │ custom_comparator │ │
│ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
cpp
// 迭代器模式在STL中的应用示例
class VectorIteratorExample {
public:
void demonstrateIteratorPattern() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 迭代器模式 - 统一的访问接口
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::list<int> lst = {1, 2, 3, 4, 5};
// 相同的迭代器接口,不同的内部实现
for (auto it = lst.begin(); it != lst.end(); ++it) {
std::cout << *it << " ";
}
}
};
// 策略模式在STL中的应用示例
class StrategyPatternExample {
public:
void demonstrateSortStrategies() {
std::vector<int> vec = {5, 2, 8, 1, 9};
// 策略1:升序排序
std::sort(vec.begin(), vec.end(), std::less<int>());
// 策略2:降序排序
std::sort(vec.begin(), vec.end(), std::greater<int>());
// 策略3:自定义比较策略
auto customComparator = [](int a, int b) {
return abs(a) < abs(b); // 按绝对值排序
};
std::sort(vec.begin(), vec.end(), customComparator);
}
};
2.2 关联容器设计模式对比
关联容器内部结构对比图
┌─────────────────────────────────────────────────────────────┐
│ 红黑树容器 (set/map) │
│ │
│ ┌─────────┐ │
│ │ Root │ │
│ │ Node │ │
│ └─────────┘ │
│ ╱ ╲ │
│ ┌─────────┐ ┌─────────┐ │
│ │ Black │ │ Red │ │
│ │ Node │ │ Node │ │
│ └─────────┘ └─────────┘ │
│ ╱ ╲ ╱ ╲ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Leaf │ │ Leaf │ │ Leaf │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ 特点:O(log n) 查找/插入/删除,有序存储 │
├─────────────────────────────────────────────────────────────┤
│ 哈希表容器 (unordered_set/map) │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Hash Table (Buckets Array) │ │
│ ├─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────────┤ │
│ │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ ... │ │
│ └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────────┘ │
│ │ │ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ ▼ ▼ │
│ NULL Node1 NULL Node3 NULL Node5 NULL │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ Node2 NULL Node6 │
│ │ │ │
│ ▼ ▼ │
│ NULL NULL │
│ │
│ 特点:平均O(1) 查找/插入/删除,无序存储 │
└─────────────────────────────────────────────────────────────┘
cpp
// 关联容器性能对比示例
class AssociativeContainerComparison {
private:
std::set<int> orderedSet;
std::unordered_set<int> hashSet;
std::map<std::string, int> orderedMap;
std::unordered_map<std::string, int> hashMap;
public:
void performanceComparison() {
// 有序容器 - 红黑树实现
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 100000; ++i) {
orderedSet.insert(i); // O(log n)
}
auto end = std::chrono::high_resolution_clock::now();
auto orderedTime = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
// 哈希容器 - 哈希表实现
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 100000; ++i) {
hashSet.insert(i); // 平均O(1)
}
end = std::chrono::high_resolution_clock::now();
auto hashTime = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "有序容器插入时间: " << orderedTime.count() << " 微秒\n";
std::cout << "哈希容器插入时间: " << hashTime.count() << " 微秒\n";
}
void demonstrateOrdering() {
// 有序容器自动排序
std::set<int> s = {5, 2, 8, 1, 9};
std::cout << "有序集合: ";
for (int val : s) {
std::cout << val << " "; // 输出: 1 2 5 8 9
}
std::cout << "\n";
// 哈希容器不保证顺序
std::unordered_set<int> us = {5, 2, 8, 1, 9};
std::cout << "哈希集合: ";
for (int val : us) {
std::cout << val << " "; // 输出顺序不定
}
std::cout << "\n";
}
};
2.3 容器适配器的适配器模式应用
容器适配器模式结构图
┌─────────────────────────────────────────────────────────────┐
│ 适配器模式应用 │
│ │
│ ┌─────────────┐ 适配 ┌─────────────────────────┐ │
│ │ Client │◀─────────────│ Adapter │ │
│ │ Code │ │ (stack) │ │
│ │ │ │ (queue) │ │
│ └─────────────┘ └─────────────────────────┘ │
│ │ │
│ 控制访问 │
│ │ │
│ ▼ │
│ ┌─────────────────────────┐ │
│ │ Adaptee Container │ │
│ │ (vector) │ │
│ │ (deque) │ │
│ │ (list) │ │
│ └─────────────────────────┘ │
│ │
│ 适配器提供特定接口,隐藏底层容器的复杂性 │
└─────────────────────────────────────────────────────────────┘
cpp
// 自定义容器适配器示例,展示适配器模式
template<typename T, typename Container = std::deque<T>>
class CustomStack {
private:
Container container; // 被适配的容器
public:
// 适配器接口
void push(const T& item) {
container.push_back(item); // 适配为栈的push操作
}
void pop() {
if (!container.empty()) {
container.pop_back(); // 适配为栈的pop操作
}
}
T& top() const {
return container.back(); // 适配为栈的top操作
}
bool empty() const {
return container.empty();
}
size_t size() const {
return container.size();
}
};
// 使用示例
class StackAdapterExample {
public:
void demonstrateAdapter() {
// 使用不同的底层容器
CustomStack<int, std::vector<int>> vectorStack;
CustomStack<int, std::deque<int>> dequeStack;
CustomStack<int, std::list<int>> listStack;
// 相同的接口,不同的实现
vectorStack.push(1);
vectorStack.push(2);
dequeStack.push(10);
dequeStack.push(20);
listStack.push(100);
listStack.push(200);
// 统一的使用方式
std::cout << "Vector Stack top: " << vectorStack.top() << "\n";
std::cout << "Deque Stack top: " << dequeStack.top() << "\n";
std::cout << "List Stack top: " << listStack.top() << "\n";
}
};
3. 迭代器设计模式深度分析
迭代器继承层次与访问模式对比
┌─────────────────────────────────────────────────────────────┐
│ 迭代器类型能力对比 │
│ │
│ Input Iterator │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 能力: →读取 操作: ++it, *it │ │
│ │ 示例: std::istream_iterator │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ 继承 │
│ Forward Iterator │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 能力: →读取 →写入 操作: ++it, *it = value │ │
│ │ 示例: std::forward_list::iterator │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ 继承 │
│ Bidirectional Iterator │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 能力: ←→读写 操作: ++it, --it, *it │ │
│ │ 示例: std::list::iterator, std::set::iterator │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ 继承 │
│ Random Access Iterator │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 能力: 随机访问 操作: it+n, it[n], it1-it2 │ │
│ │ 示例: std::vector::iterator, std::deque::iterator │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
cpp
// 迭代器模式在不同容器中的实现对比
class IteratorPatternDemo {
public:
void demonstrateIteratorCapabilities() {
// 随机访问迭代器 - vector
std::vector<int> vec = {1, 2, 3, 4, 5};
auto vecIt = vec.begin();
// 随机访问能力
std::cout << "Vector[2]: " << vecIt[2] << "\n"; // 直接索引
std::cout << "Vector+3: " << *(vecIt + 3) << "\n"; // 指针运算
// 双向迭代器 - list
std::list<int> lst = {1, 2, 3, 4, 5};
auto lstIt = lst.begin();
// 只能前进和后退,不能随机访问
++lstIt; // 前进
++lstIt;
--lstIt; // 后退
std::cout << "List current: " << *lstIt << "\n";
// lstIt[2]; // 编译错误!list迭代器不支持随机访问
// lstIt + 3; // 编译错误!
// 前向迭代器 - forward_list
std::forward_list<int> flst = {1, 2, 3, 4, 5};
auto flstIt = flst.begin();
// 只能前进,不能后退
++flstIt; // 前进
// --flstIt; // 编译错误!forward_list迭代器不支持后退
std::cout << "Forward list current: " << *flstIt << "\n";
}
// 算法如何利用迭代器能力
template<typename Iterator>
void efficientAdvance(Iterator& it,
typename std::iterator_traits<Iterator>::difference_type n) {
using IterCategory = typename std::iterator_traits<Iterator>::iterator_category;
if constexpr (std::is_same_v<IterCategory, std::random_access_iterator_tag>) {
// 随机访问迭代器 - O(1)
it += n;
std::cout << "使用随机访问: O(1)\n";
} else {
// 其他迭代器 - O(n)
for (auto i = 0; i < n; ++i) {
++it;
}
std::cout << "使用顺序访问: O(n)\n";
}
}
};
4. 算法中的设计模式应用
STL算法设计模式架构图
┌─────────────────────────────────────────────────────────────┐
│ 模板方法模式 │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ std::sort 算法骨架 │ │
│ │ │ │
│ │ 1. 检查迭代器类型 │ │
│ │ 2. 选择排序策略 │ │
│ │ 3. if (随机访问) → 快速排序 │ │
│ │ else → 堆排序 │ │
│ │ 4. 调用比较函数 (可自定义) │ │
│ │ 5. 递归或迭代执行 │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ 策略模式 │
│ │
│ ┌─────────────┐ 使用策略 ┌─────────────────────────┐ │
│ │ 算法 │◀──────────────│ 比较策略 │ │
│ │ std::sort │ │ std::less<T> │ │
│ │ std::find │ │ std::greater<T> │ │
│ │ std::search │ │ CustomComparator │ │
│ └─────────────┘ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
cpp
// 算法中设计模式的应用示例
class AlgorithmPatternDemo {
public:
// 模板方法模式 - 算法骨架固定,细节可变
template<typename Iterator, typename Predicate>
Iterator customFind(Iterator first, Iterator last, Predicate pred) {
// 算法骨架(模板方法)
while (first != last) {
if (pred(*first)) { // 策略模式 - 可变的查找条件
return first;
}
++first;
}
return last;
}
// 策略模式 - 不同的比较策略
class ComparisonStrategies {
public:
// 策略1:按值比较
struct ValueComparator {
bool operator()(int a, int b) const {
return a < b;
}
};
// 策略2:按绝对值比较
struct AbsoluteComparator {
bool operator()(int a, int b) const {
return std::abs(a) < std::abs(b);
}
};
// 策略3:自定义复杂比较
struct CustomComparator {
bool operator()(int a, int b) const {
// 偶数优先,然后按值排序
if (a % 2 == 0 && b % 2 != 0) return true;
if (a % 2 != 0 && b % 2 == 0) return false;
return a < b;
}
};
};
void demonstrateAlgorithmPatterns() {
std::vector<int> data = {-5, 2, -8, 1, 9, -3, 4};
// 使用不同策略排序
auto data1 = data;
std::sort(data1.begin(), data1.end(), ComparisonStrategies::ValueComparator{});
std::cout << "按值排序: ";
for (int val : data1) std::cout << val << " ";
std::cout << "\n";
auto data2 = data;
std::sort(data2.begin(), data2.end(), ComparisonStrategies::AbsoluteComparator{});
std::cout << "按绝对值排序: ";
for (int val : data2) std::cout << val << " ";
std::cout << "\n";
auto data3 = data;
std::sort(data3.begin(), data3.end(), ComparisonStrategies::CustomComparator{});
std::cout << "自定义排序: ";
for (int val : data3) std::cout << val << " ";
std::cout << "\n";
// 使用自定义查找算法
auto result = customFind(data.begin(), data.end(), [](int x) { return x > 5; });
if (result != data.end()) {
std::cout << "找到大于5的数: " << *result << "\n";
}
}
};
5. 函数对象中的命令模式
函数对象命令模式结构图
┌─────────────────────────────────────────────────────────────┐
│ 命令模式在函数对象中的应用 │
│ │
│ ┌─────────────┐ 封装操作 ┌─────────────────────────┐ │
│ │ Client │◀────────────────│ Command │ │
│ │ Algorithm │ │ (Function Object) │ │
│ └─────────────┘ └─────────────────────────┘ │
│ │ │ │
│ │ 封装具体操作 │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ std::sort │ │ std::plus<T> │ │
│ │ std::find │ │ std::multiplies<T> │ │
│ │ std::transform │ CustomFunctor │ │
│ └─────────────┘ │ Lambda Expression │ │
│ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
cpp
// 函数对象中的命令模式应用
class FunctionObjectCommandPattern {
public:
// 命令接口
class MathCommand {
public:
virtual ~MathCommand() = default;
virtual double execute(double a, double b) const = 0;
virtual std::string getName() const = 0;
};
// 具体命令实现
class AddCommand : public MathCommand {
public:
double execute(double a, double b) const override {
return a + b;
}
std::string getName() const override { return "Add"; }
};
class MultiplyCommand : public MathCommand {
public:
double execute(double a, double b) const override {
return a * b;
}
std::string getName() const override { return "Multiply"; }
};
// 命令调用者
class Calculator {
private:
std::vector<std::unique_ptr<MathCommand>> history;
public:
double compute(double a, double b, std::unique_ptr<MathCommand> cmd) {
double result = cmd->execute(a, b);
std::cout << "执行命令: " << cmd->getName()
<< "(" << a << ", " << b << ") = " << result << "\n";
history.push_back(std::move(cmd));
return result;
}
void printHistory() const {
std::cout << "命令历史:\n";
for (const auto& cmd : history) {
std::cout << "- " << cmd->getName() << "\n";
}
}
};
// 使用STL函数对象的命令模式
void demonstrateSTLFunctionObjects() {
std::vector<int> data = {1, 2, 3, 4, 5};
// 命令1:transform with multiplies
std::transform(data.begin(), data.end(), data.begin(),
std::bind(std::multiplies<int>(), std::placeholders::_1, 2));
// 命令2:lambda命令
auto squareCommand = [](int x) { return x * x; };
std::transform(data.begin(), data.end(), data.begin(), squareCommand);
// 命令3:自定义函数对象
struct ModuloCommand {
int divisor;
ModuloCommand(int d) : divisor(d) {}
int operator()(int x) const { return x % divisor; }
};
std::transform(data.begin(), data.end(), data.begin(), ModuloCommand(10));
for (int val : data) {
std::cout << val << " ";
}
std::cout << "\n";
}
void demonstrateCommandPattern() {
Calculator calc;
calc.compute(10, 5, std::make_unique<AddCommand>());
calc.compute(10, 5, std::make_unique<MultiplyCommand>());
calc.printHistory();
}
};
8. STL性能优化的设计模式应用
8.1 享元模式在字符串处理中的应用
字符串享元模式优化对比
┌─────────────────────────────────────────────────────────────┐
│ 传统字符串处理 │
│ │
│ 每个字符串对象都独立存储数据 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ string1 │ │ string2 │ │ string3 │ │
│ │ "Hello" │ │ "Hello" │ │ "Hello" │ │
│ │ [H][e][l] │ │ [H][e][l] │ │ [H][e][l] │ │
│ │ [l][o] │ │ [l][o] │ │ [l][o] │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ 内存使用:3 × 5 = 15 字节 │
├─────────────────────────────────────────────────────────────┤
│ 享元模式优化 │
│ │
│ 多个对象共享相同的内在状态 │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ string1 │ │ string2 │ │ string3 │ │
│ │ ptr ──────┐ │ │ ptr ──────┐ │ │ ptr ──────┐ │ │
│ └───────────┼─┘ └───────────┼─┘ └───────────┼─┘ │
│ │ │ │ │
│ └───────────────┼───────────────┘ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ 共享字符串数据 │ │
│ │ "Hello" │ │
│ │ [H][e][l][l][o] │ │
│ └─────────────────────┘ │
│ │
│ 内存使用:3 × sizeof(ptr) + 5 = 约17字节(但避免重复) │
└─────────────────────────────────────────────────────────────┘
cpp
// 享元模式在字符串处理中的应用
class StringFlyweightPattern {
private:
// 享元工厂
class StringPool {
private:
static std::unordered_map<std::string, std::shared_ptr<std::string>> pool;
public:
static std::shared_ptr<std::string> getString(const std::string& str) {
auto it = pool.find(str);
if (it != pool.end()) {
std::cout << "复用字符串: " << str << "\n";
return it->second;
} else {
std::cout << "创建新字符串: " << str << "\n";
auto newStr = std::make_shared<std::string>(str);
pool[str] = newStr;
return newStr;
}
}
static size_t getPoolSize() {
return pool.size();
}
static void printPoolStats() {
std::cout << "字符串池大小: " << pool.size() << "\n";
for (const auto& pair : pool) {
std::cout << "- \"" << pair.first << "\" (引用计数: "
<< pair.second.use_count() << ")\n";
}
}
};
public:
// 使用享元模式的字符串类
class OptimizedString {
private:
std::shared_ptr<std::string> flyweight;
public:
OptimizedString(const std::string& str)
: flyweight(StringPool::getString(str)) {}
const std::string& getValue() const {
return *flyweight;
}
size_t size() const {
return flyweight->size();
}
};
void demonstrateFlyweightPattern() {
std::vector<OptimizedString> strings;
// 创建多个相同的字符串
strings.emplace_back("Hello");
strings.emplace_back("World");
strings.emplace_back("Hello"); // 复用
strings.emplace_back("World"); // 复用
strings.emplace_back("Hello"); // 复用
StringPool::printPoolStats();
std::cout << "存储的字符串:\n";
for (const auto& str : strings) {
std::cout << "- " << str.getValue() << "\n";
}
}
};
// 静态成员定义
std::unordered_map<std::string, std::shared_ptr<std::string>>
StringFlyweightPattern::StringPool::pool;
8.2 代理模式在智能指针中的应用
智能指针代理模式结构图
┌─────────────────────────────────────────────────────────────┐
│ 智能指针代理模式 │
│ │
│ ┌─────────────┐ 代理访问 ┌─────────────────────────┐ │
│ │ Client │◀───────────────│ Smart Pointer │ │
│ │ Code │ │ (Proxy Object) │ │
│ └─────────────┘ └─────────────────────────┘ │
│ │ │
│ 控制访问 │
│ │ │
│ ▼ │
│ ┌─────────────────────────┐ │
│ │ Real Object │ │
│ │ (Actual Data) │ │
│ └─────────────────────────┘ │
│ │
│ 代理功能: │
│ • 自动内存管理 │
│ • 引用计数 │
│ • 线程安全 │
│ • 空指针检查 │
└─────────────────────────────────────────────────────────────┘
cpp
// 智能指针中的代理模式应用
template<typename T>
class SmartPointerProxy {
private:
T* ptr;
size_t* refCount;
std::mutex* mtx;
void release() {
if (refCount) {
std::lock_guard<std::mutex> lock(*mtx);
(*refCount)--;
if (*refCount == 0) {
delete ptr;
delete refCount;
delete mtx;
}
}
}
void addRef() {
if (refCount) {
std::lock_guard<std::mutex> lock(*mtx);
(*refCount)++;
}
}
public:
// 构造函数
explicit SmartPointerProxy(T* p = nullptr)
: ptr(p), refCount(nullptr), mtx(nullptr) {
if (ptr) {
refCount = new size_t(1);
mtx = new std::mutex();
}
}
// 拷贝构造函数
SmartPointerProxy(const SmartPointerProxy& other)
: ptr(other.ptr), refCount(other.refCount), mtx(other.mtx) {
addRef();
}
// 赋值操作符
SmartPointerProxy& operator=(const SmartPointerProxy& other) {
if (this != &other) {
release();
ptr = other.ptr;
refCount = other.refCount;
mtx = other.mtx;
addRef();
}
return *this;
}
// 析构函数
~SmartPointerProxy() {
release();
}
// 代理方法 - 提供受控访问
T& operator*() const {
if (!ptr) throw std::runtime_error("Null pointer dereference");
return *ptr;
}
T* operator->() const {
if (!ptr) throw std::runtime_error("Null pointer dereference");
return ptr;
}
// 获取引用计数
size_t getRefCount() const {
if (refCount) {
std::lock_guard<std::mutex> lock(*mtx);
return *refCount;
}
return 0;
}
// 检查是否为空
bool isNull() const {
return ptr == nullptr;
}
// 重置指针
void reset(T* newPtr = nullptr) {
release();
ptr = newPtr;
if (ptr) {
refCount = new size_t(1);
mtx = new std::mutex();
} else {
refCount = nullptr;
mtx = nullptr;
}
}
};
// 使用示例
class ProxyPatternDemo {
public:
void demonstrateSmartPointerProxy() {
{
SmartPointerProxy<std::string> ptr1(new std::string("Hello"));
std::cout << "ptr1 引用计数: " << ptr1.getRefCount() << "\n";
std::cout << "ptr1 值: " << *ptr1 << "\n";
{
SmartPointerProxy<std::string> ptr2 = ptr1; // 拷贝
std::cout << "ptr1 引用计数: " << ptr1.getRefCount() << "\n";
std::cout << "ptr2 引用计数: " << ptr2.getRefCount() << "\n";
SmartPointerProxy<std::string> ptr3(new std::string("World"));
ptr3 = ptr1; // 赋值
std::cout << "赋值后 ptr1 引用计数: " << ptr1.getRefCount() << "\n";
} // ptr2 和 ptr3 超出作用域
std::cout << "ptr2, ptr3 销毁后 ptr1 引用计数: " << ptr1.getRefCount() << "\n";
} // ptr1 超出作用域,自动释放内存
std::cout << "所有智能指针销毁,内存已释放\n";
}
};
结论
通过这些详细的图表对比和C++代码示例,我们可以清楚地看到设计模式在STL中的广泛应用。这些模式不仅提高了代码的可重用性和可维护性,还为STL提供了高效、灵活的实现方案。理解这些模式的应用有助于我们更好地使用STL,并在自己的项目中应用类似的设计思想。