C++设计模式学习详解(23种)

C++设计模式学习详解

设计模式是软件开发中常见问题的可复用解决方案。它们不是可以直接转换为代码的成品,而是描述解决问题的通用方法。C++ 中常用的设计模式可以分为三大类:创建型模式、结构型模式和行为型模式。

一、创建型模式 (Creational Patterns)

创建型模式关注对象的创建过程,隐藏创建对象的细节,将客户端与对象的创建过程解耦。

1. 单例模式 (Singleton)

意图: 保证一个类只有一个实例,并提供一个全局访问点。

适用场景:

  • 需要确保某个类只有一个实例,例如数据库连接池、日志管理器等。
  • 需要全局访问某个类的实例。

实现: 将类的构造函数设为私有,提供一个静态方法获取实例。

代码示例:

class Singleton {
    
    
private:
  Singleton() {
    
    } // 私有构造函数
  static Singleton* instance; // 静态成员变量,指向唯一的实例
public:
  static Singleton* getInstance() {
    
     // 静态方法,获取实例
    if (instance == nullptr) {
    
    
      instance = new Singleton();
    }
    return instance;
  }
  // ...其他成员函数和变量...
};

Singleton* Singleton::instance = nullptr; // 初始化静态成员变量

int main() {
    
    
  Singleton* s1 = Singleton::getInstance();
  Singleton* s2 = Singleton::getInstance();
  // s1 和 s2 指向同一个实例
  return 0;
}

2. 工厂方法模式 (Factory Method)

意图: 定义一个创建对象的接口,但由子类决定实例化哪个类。工厂方法让类把实例化推迟到子类。

适用场景:

  • 当一个类不知道它所必须创建的对象的类的时候。
  • 当一个类希望由其子类来指定所创建的对象的时候。
  • 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。

实现: 定义一个抽象工厂类,具体工厂类继承抽象工厂类并实现创建具体产品的方法。

代码示例:

// 产品接口
class Product {
    
    
public:
  virtual void operation() = 0;
};

// 具体产品
class ConcreteProductA : public Product {
    
    
public:
  void operation() override {
    
     
    std::cout << "ConcreteProductA operation" << std::endl; 
  }
};

class ConcreteProductB : public Product {
    
    
public:
  void operation() override {
    
     
    std::cout << "ConcreteProductB operation" << std::endl; 
  }
};

// 抽象工厂
class Creator {
    
    
public:
  virtual Product* factoryMethod() = 0;
};

// 具体工厂
class ConcreteCreatorA : public Creator {
    
    
public:
  Product* factoryMethod() override {
    
     
    return new ConcreteProductA(); 
  }
};

class ConcreteCreatorB : public Creator {
    
    
public:
  Product* factoryMethod() override {
    
     
    return new ConcreteProductB(); 
  }
};

int main() {
    
    
  Creator* creatorA = new ConcreteCreatorA();
  Product* productA = creatorA->factoryMethod();
  productA->operation(); // 输出 "ConcreteProductA operation"

  Creator* creatorB = new ConcreteCreatorB();
  Product* productB = creatorB->factoryMethod();
  productB->operation(); // 输出 "ConcreteProductB operation"

  delete creatorA;
  delete productA;
  delete creatorB;
  delete productB;
  return 0;
}

3. 抽象工厂模式 (Abstract Factory)

意图: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

适用场景:

  • 一个系统要独立于它的产品的创建、组合和表示时。
  • 一个系统要由多个产品系列中的一个来配置时。
  • 当你要强调一系列相关的产品对象的设计以便进行联合使用时。
  • 当你提供一个产品类库,而只想显示它们的接口而不是实现时。

实现: 定义一个抽象工厂接口,具体工厂类实现该接口并创建一系列相关产品。

代码示例:

// 抽象产品A
class AbstractProductA {
    
    
public:
  virtual void operationA() = 0;
};

// 抽象产品B
class AbstractProductB {
    
    
public:
  virtual void operationB() = 0;
};

// 具体产品A1
class ConcreteProductA1 : public AbstractProductA {
    
    
public:
  void operationA() override {
    
     
      std::cout << "ConcreteProductA1 operation" << std::endl; 
  }
};

// 具体产品A2
class ConcreteProductA2 : public AbstractProductA {
    
    
public:
  void operationA() override {
    
     
      std::cout << "ConcreteProductA2 operation" << std::endl; 
  }
};

// 具体产品B1
class ConcreteProductB1 : public AbstractProductB {
    
    
public:
  void operationB() override {
    
     
      std::cout << "ConcreteProductB1 operation" << std::endl; 
  }
};

// 具体产品B2
class ConcreteProductB2 : public AbstractProductB {
    
    
public:
  void operationB() override {
    
     
      std::cout << "ConcreteProductB2 operation" << std::endl; 
  }
};

// 抽象工厂
class AbstractFactory {
    
    
public:
  virtual AbstractProductA* createProductA() = 0;
  virtual AbstractProductB* createProductB() = 0;
};

// 具体工厂1
class ConcreteFactory1 : public AbstractFactory {
    
    
public:
  AbstractProductA* createProductA() override {
    
     return new ConcreteProductA1(); }
  AbstractProductB* createProductB() override {
    
     return new ConcreteProductB1(); }
};

// 具体工厂2
class ConcreteFactory2 : public AbstractFactory {
    
    
public:
  AbstractProductA* createProductA() override {
    
     return new ConcreteProductA2(); }
  AbstractProductB* createProductB() override {
    
     return new ConcreteProductB2(); }
};

int main() {
    
    
  AbstractFactory* factory1 = new ConcreteFactory1();
  AbstractProductA* productA1 = factory1->createProductA();
  AbstractProductB* productB1 = factory1->createProductB();
  productA1->operationA(); // 输出 "ConcreteProductA1 operation"
  productB1->operationB(); // 输出 "ConcreteProductB1 operation"

  AbstractFactory* factory2 = new ConcreteFactory2();
  AbstractProductA* productA2 = factory2->createProductA();
  AbstractProductB* productB2 = factory2->createProductB();
  productA2->operationA(); // 输出 "ConcreteProductA2 operation"
  productB2->operationB(); // 输出 "ConcreteProductB2 operation"

  delete factory1;
  delete productA1;
  delete productB1;
  delete factory2;
  delete productA2;
  delete productB2;

  return 0;
}

区别:

  • 工厂方法模式:一个抽象产品,多个具体产品,一个抽象工厂,多个具体工厂,每个具体工厂生产一个具体产品。
  • 抽象工厂模式:多个抽象产品,多个具体产品,一个抽象工厂,多个具体工厂,每个具体工厂生产一系列相关的具体产品。

简单来说,工厂方法模式用于创建单个产品,而抽象工厂模式用于创建一系列相关产品。

4. 建造者模式 (Builder)

意图: 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。

实现: 定义一个抽象建造者类,具体建造者类继承抽象建造者类并实现构建对象的各个部件。一个指挥者类负责指导建造者构建对象。

代码示例:

// 产品类
class Product {
    
    
public:
  void setPartA(const std::string& partA) {
    
     this->partA = partA; }
  void setPartB(const std::string& partB) {
    
     this->partB = partB; }
  // ... 其他部件
private:
  std::string partA;
  std::string partB;
  // ... 其他部件
};

// 抽象建造者
class Builder {
    
    
public:
  virtual void buildPartA() = 0;
  virtual void buildPartB() = 0;
  // ... 其他构建部件方法
  virtual Product* getResult() = 0;
};

// 具体建造者
class ConcreteBuilder : public Builder {
    
    
public:
  void buildPartA() override {
    
     product.setPartA("PartA"); }
  void buildPartB() override {
    
     product.setPartB("PartB"); }
  // ... 其他构建部件方法
  Product* getResult() override {
    
     return &product; }
private:
  Product product;
};

// 指挥者
class Director {
    
    
public:
  void construct(Builder* builder) {
    
    
    builder->buildPartA();
    builder->buildPartB();
    // ... 其他构建步骤
  }
};

5. 原型模式 (Prototype)

意图: 使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

实现: 定义一个原型接口,具体原型类实现该接口并实现克隆自身的方法。

代码示例:

// 原型接口
class Prototype {
    
    
public:
  virtual Prototype* clone() const = 0;
};

// 具体原型
class ConcretePrototype1 : public Prototype {
    
    
public:
  Prototype* clone() const override {
    
     return new ConcretePrototype1(*this); }
};

class ConcretePrototype2 : public Prototype {
    
    
public:
  Prototype* clone() const override {
    
     return new ConcretePrototype2(*this); }
};

二、结构型模式 (Structural Patterns)

结构型模式关注如何将类和对象组合成更大的结构,以简化结构和增加灵活性。

6. 适配器模式 (Adapter)

意图: 将一个类的接口转换成客户端所期望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

实现: 定义一个适配器类,该类持有被适配类的实例,并实现目标接口。

代码示例:

// 目标接口
class Target {
    
    
public:
  virtual void request() = 0;
};

// 被适配类
class Adaptee {
    
    
public:
  void specificRequest() {
    
     /* ... */ }
};

// 适配器类
class Adapter : public Target {
    
    
public:
  void request() override {
    
     adaptee.specificRequest(); }
private:
  Adaptee adaptee;
};

7. 桥接模式 (Bridge)

意图: 将抽象部分与它的实现部分分离,使它们都可以独立地变化。

实现: 定义一个抽象类和一个实现类接口,抽象类持有实现类接口的实例。

代码示例:

// 抽象部分
class Abstraction {
    
    
public:
  virtual void operation() = 0;
protected:
  Implementation* implementation;
};

// 实现部分接口
class Implementation {
    
    
public:
  virtual void operationImpl() = 0;
};

// 具体抽象
class RefinedAbstraction : public Abstraction {
    
    
public:
  void operation() override {
    
     implementation->operationImpl(); }
};

// 具体实现
class ConcreteImplementationA : public Implementation {
    
    
public:
  void operationImpl() override {
    
     /* ... */ }
};

class ConcreteImplementationB : public Implementation {
    
    
public:
  void operationImpl() override {
    
     /* ... */ }
};

8. 装饰器模式 (Decorator)

意图: 动态地给一个对象添加一些额外的职责。就扩展功能而言,它比生成子类方式更为灵活。

实现: 定义一个装饰器类,该类继承自被装饰类的基类,并持有被装饰类的实例。

代码示例:

// 组件接口
class Component {
    
    
public:
  virtual void operation() = 0;
};

// 具体组件
class ConcreteComponent : public Component {
    
    
public:
  void operation() override {
    
     /* ... */ }
};

// 装饰器基类
class Decorator : public Component {
    
    
public:
  Decorator(Component* component) : component(component) {
    
    }
  void operation() override {
    
     component->operation(); }
protected:
  Component* component;
};

// 具体装饰器
class ConcreteDecoratorA : public Decorator {
    
    
public:
  ConcreteDecoratorA(Component* component) : Decorator(component) {
    
    }
  void operation() override {
    
    
    // 添加额外的职责
    Decorator::operation(); 
  }
};

9. 组合模式 (Composite)

意图: 将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

实现: 定义一个组件接口,叶子节点和组合节点都实现该接口。组合节点持有组件接口的实例列表。

代码示例:

// 组件接口
class Component {
    
    
public:
  virtual void operation() = 0;
  virtual void add(Component* component) = 0;
  virtual void remove(Component* component) = 0;
  virtual Component* getChild(int index) = 0;
};

// 叶子节点
class Leaf : public Component {
    
    
public:
  void operation() override {
    
     /* ... */ }
  void add(Component* component) override {
    
     /* ... */ }
  void remove(Component* component) override {
    
     /* ... */ }
  Component* getChild(int index) override {
    
     /* ... */ }
};

// 组合节点
class Composite : public Component {
    
    
public:
  void operation() override {
    
     
    for (auto& child : children) {
    
    
      child->operation();
    }
  }
  void add(Component* component) override {
    
     children.push_back(component); }
  void remove(Component* component) override {
    
     /* ... */ }
  Component* getChild(int index) override {
    
     return children[index]; }
private:
  std::vector<Component*> children;
};

10. 外观模式 (Facade)

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

实现: 定义一个外观类,该类持有子系统各个类的实例,并提供简化的接口。

代码示例:

// 子系统类
class SubsystemA {
    
    
public:
  void operationA() {
    
     /* ... */ }
};

class SubsystemB {
    
    
public:
  void operationB() {
    
     /* ... */ }
};

class SubsystemC {
    
    
public:
  void operationC() {
    
     /* ... */ }
};

// 外观类
class Facade {
    
    
public:
  void operation() {
    
    
    subsystemA.operationA();
    subsystemB.operationB();
    subsystemC.operationC();
  }
private:
  SubsystemA subsystemA;
  SubsystemB subsystemB;
  SubsystemC subsystemC;
};

11. 享元模式 (Flyweight)

意图: 运用共享技术有效地支持大量细粒度的对象。

实现: 将对象的状态分为内部状态和外部状态,内部状态可以共享,外部状态由客户端提供。

代码示例:

// 享元接口
class Flyweight {
    
    
public:
  virtual void operation(const std::string& extrinsicState) = 0;
};

// 具体享元
class ConcreteFlyweight : public Flyweight {
    
    
public:
  void operation(const std::string& extrinsicState) override {
    
    
    // 使用 intrinsicState 和 extrinsicState 进行操作
  }
private:
  std::string intrinsicState;
};

// 享元工厂
class FlyweightFactory {
    
    
public:
  Flyweight* getFlyweight(const std::string& key) {
    
    
    if (flyweights.count(key)) {
    
    
      return flyweights[key];
    } else {
    
    
      Flyweight* flyweight = new ConcreteFlyweight();
      flyweights[key] = flyweight;
      return flyweight;
    }
  }
private:
  std::map<std::string, Flyweight*> flyweights;
};

12. 代理模式 (Proxy)

意图: 为其他对象提供一种代理以控制对这个对象的访问。

实现: 定义一个代理类,该类持有被代理对象的实例,并控制对被代理对象的访问。

代码示例:

// 主题接口
class Subject {
    
    
public:
  virtual void request() = 0;
};

// 真实主题
class RealSubject : public Subject {
    
    
public:
  void request() override {
    
     /* ... */ }
};

// 代理
class Proxy : public Subject {
    
    
public:
  void request() override {
    
    
    // 控制对 RealSubject 的访问
    realSubject.request();
  }
private:
  RealSubject realSubject;
};

三、行为型模式 (Behavioral Patterns)

行为型模式关注对象之间的交互和职责的分配。

13. 责任链模式 (Chain of Responsibility)

意图: 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

实现: 定义一个处理器接口,具体处理器类实现该接口并持有下一个处理器的实例。

代码示例:

// 处理器接口
class Handler {
    
    
public:
  virtual void handleRequest(int request) = 0;
  void setNextHandler(Handler* handler) {
    
     nextHandler = handler; }
protected:
  Handler* nextHandler;
};

// 具体处理器
class ConcreteHandler1 : public Handler {
    
    
public:
  void handleRequest(int request) override {
    
    
    if (request < 10) {
    
    
      // 处理请求
    } else if (nextHandler != nullptr) {
    
    
      nextHandler->handleRequest(request);
    }
  }
};

class ConcreteHandler2 : public Handler {
    
    
public:
  void handleRequest(int request) override {
    
    
    if (request >= 10 && request < 20) {
    
    
      // 处理请求
    } else if (nextHandler != nullptr) {
    
    
      nextHandler->handleRequest(request);
    }
  }
};

14. 命令模式 (Command)

意图: 将一个请求封装为一个对象,从而使你可用不同的请求对客户端进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

实现: 定义一个命令接口,具体命令类实现该接口并持有接收者对象的实例。

代码示例:

// 命令接口
class Command {
    
    
public:
  virtual void execute() = 0;
};

// 具体命令
class ConcreteCommand : public Command {
    
    
public:
  ConcreteCommand(Receiver* receiver) : receiver(receiver) {
    
    }
  void execute() override {
    
     receiver->action(); }
private:
  Receiver* receiver;
};

// 接收者
class Receiver {
    
    
public:
  void action() {
    
     /* ... */ }
};

15. 解释器模式 (Interpreter)

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

实现: 定义一个抽象表达式接口,具体表达式类实现该接口并解释对应的语法规则。

代码示例:

// 抽象表达式
class Expression {
    
    
public:
  virtual int interpret() = 0;
};

// 终结符表达式
class Number : public Expression {
    
    
public:
  Number(int number) : number(number) {
    
    }
  int interpret() override {
    
     return number; }
private:
  int number;
};

// 非终结符表达式
class Add : public Expression {
    
    
public:
  Add(Expression* left, Expression* right) : left(left), right(right) {
    
    }
  int interpret() override {
    
     return left->interpret() + right->interpret(); }
private:
  Expression* left;
  Expression* right;
};

16. 迭代器模式 (Iterator)

意图: 提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。

实现: 定义一个迭代器接口,具体迭代器类实现该接口并持有聚合对象的实例。

代码示例:

// 聚合接口
class Aggregate {
    
    
public:
  virtual Iterator* createIterator() = 0;
};

// 迭代器接口
class Iterator {
    
    
public:
  virtual bool hasNext() = 0;
  virtual int next() = 0;
};

// 具体聚合
class ConcreteAggregate : public Aggregate {
    
    
public:
  Iterator* createIterator() override {
    
     return new ConcreteIterator(this); }
  int getItem(int index) {
    
     return items[index]; }
  int getSize() {
    
     return items.size(); }
private:
  std::vector<int> items;
};

// 具体迭代器
class ConcreteIterator : public Iterator {
    
    
public:
  ConcreteIterator(ConcreteAggregate* aggregate) : aggregate(aggregate), index(0) {
    
    }
  bool hasNext() override {
    
     return index < aggregate->getSize(); }
  int next() override {
    
     return aggregate->getItem(index++); }
private:
  ConcreteAggregate* aggregate;
  int index;
};

17. 中介者模式 (Mediator)

意图: 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

实现: 定义一个中介者接口,具体中介者类实现该接口并持有各个同事对象的实例。

代码示例:

// 中介者接口
class Mediator {
    
    
public:
  virtual void notify(Colleague* colleague, std::string event) = 0;
};

// 同事接口
class Colleague {
    
    
public:
  Colleague(Mediator* mediator) : mediator(mediator) {
    
    }
protected:
  Mediator* mediator;
};

// 具体中介者
class ConcreteMediator : public Mediator {
    
    
public:
  void notify(Colleague* colleague, std::string event) override {
    
    
    if (event == "A") {
    
    
      colleagueB->doB();
    } else if (event == "B") {
    
    
      colleagueA->doA();
    }
  }
  void setColleagueA(Colleague* colleague) {
    
     colleagueA = colleague; }
  void setColleagueB(Colleague* colleague) {
    
     colleagueB = colleague; }
private:
  Colleague* colleagueA;
  Colleague* colleagueB;
};

// 具体同事
class ConcreteColleagueA : public Colleague {
    
    
public:
  ConcreteColleagueA(Mediator* mediator) : Colleague(mediator) {
    
    }
  void doA() {
    
     /* ... */ }
};

class ConcreteColleagueB : public Colleague {
    
    
public:
  ConcreteColleagueB(Mediator* mediator) : Colleague(mediator) {
    
    }
  void doB() {
    
     /* ... */ }
};

18. 备忘录模式 (Memento)

意图: 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

实现: 定义一个备忘录类,用于存储对象的内部状态。发起人对象可以创建备忘录对象并恢复状态。

代码示例:

// 发起人
class Originator {
    
    
public:
  void setState(const std::string& state) {
    
     this->state = state; }
  std::string getState() {
    
     return state; }
  Memento* createMemento() {
    
     return new Memento(state); }
  void setMemento(Memento* memento) {
    
     state = memento->getState(); }
private:
  std::string state;
};

// 备忘录
class Memento {
    
    
public:
  Memento(const std::string& state) : state(state) {
    
    }
  std::string getState() {
    
     return state; }
private:
  std::string state;
};

19. 观察者模式 (Observer)

意图: 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。

实现: 定义一个主题接口和一个观察者接口,主题类持有观察者列表,并在状态改变时通知观察者。

代码示例:

// 主题接口
class Subject {
    
    
public:
  virtual void registerObserver(Observer* observer) = 0;
  virtual void removeObserver(Observer* observer) = 0;
  virtual void notifyObservers() = 0;
};

// 观察者接口
class Observer {
    
    
public:
  virtual void update(Subject* subject) = 0;
};

// 具体主题
class ConcreteSubject : public Subject {
    
    
public:
  void registerObserver(Observer* observer) override {
    
     observers.push_back(observer); }
  void removeObserver(Observer* observer) override {
    
     /* ... */ }
  void notifyObservers() override {
    
    
    for (auto& observer : observers) {
    
    
      observer->update(this);
    }
  }
  void setState(int state) {
    
     this->state = state; notifyObservers(); }
  int getState() {
    
     return state; }
private:
  std::vector<Observer*> observers;
  int state;
};

// 具体观察者
class ConcreteObserver : public Observer {
    
    
public:
  void update(Subject* subject) override {
    
    
    // 获取主题的状态更新
    ConcreteSubject* concreteSubject = dynamic_cast<ConcreteSubject*>(subject);
    int state = concreteSubject->getState();
    // ... 处理状态更新
  }
};

20. 状态模式 (State)

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

实现: 定义一个状态接口,具体状态类实现该接口并持有上下文对象的实例。上下文对象持有当前状态对象的实例。

代码示例:

// 状态接口
class State {
    
    
public:
  virtual void handle(Context* context) = 0;
};

// 上下文
class Context {
    
    
public:
  void setState(State* state) {
    
     this->state = state; }
  void request() {
    
     state->handle(this); }
private:
  State* state;
};

// 具体状态
class ConcreteStateA : public State {
    
    
public:
  void handle(Context* context) override {
    
    
    // 处理请求并可能改变上下文的状态
    context->setState(new ConcreteStateB()); 
  }
};

class ConcreteStateB : public State {
    
    
public:
  void handle(Context* context) override {
    
    
    // 处理请求并可能改变上下文的状态
  }
};

21. 策略模式 (Strategy)

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

实现: 定义一个策略接口,具体策略类实现该接口。上下文对象持有策略对象的实例。

代码示例:

// 策略接口
class Strategy {
    
    
public:
  virtual void algorithmInterface() = 0;
};

// 具体策略
class ConcreteStrategyA : public Strategy {
    
    
public:
  void algorithmInterface() override {
    
     /* ... */ }
};

class ConcreteStrategyB : public Strategy {
    
    
public:
  void algorithmInterface() override {
    
     /* ... */ }
};

// 上下文
class Context {
    
    
public:
  void setStrategy(Strategy* strategy) {
    
     this->strategy = strategy; }
  void contextInterface() {
    
     strategy->algorithmInterface(); }
private:
  Strategy* strategy;
};

22. 模板方法模式 (Template Method)

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

实现: 定义一个抽象类,该类包含一个模板方法和一些基本操作。具体子类可以重定义基本操作,但不能修改模板方法。

代码示例:

// 抽象类
class AbstractClass {
    
    
public:
  void templateMethod() {
    
    
    operation1();
    operation2();
  }
protected:
  virtual void operation1() = 0;
  virtual void operation2() = 0;
};

// 具体子类
class ConcreteClass : public AbstractClass {
    
    
protected:
  void operation1() override {
    
     /* ... */ }
  void operation2() override {
    
     /* ... */ }
};

23. 访问者模式 (Visitor)

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

实现: 定义一个访问者接口,具体访问者类实现该接口并对不同类型的元素执行不同的操作。元素类提供一个接受访问者的方法。

代码示例:

// 元素接口
class Element {
    
    
public:
  virtual void accept(Visitor* visitor) = 0;
};

// 访问者接口
class Visitor {
    
    
public:
  virtual void visitConcreteElementA(ConcreteElementA* element) = 0;
  virtual void visitConcreteElementB(ConcreteElementB* element) = 0;
};

// 具体元素
class ConcreteElementA : public Element {
    
    
public:
  void accept(Visitor* visitor) override {
    
     visitor->visitConcreteElementA(this); }
};

class ConcreteElementB : public Element {
    
    
public:
  void accept(Visitor* visitor) override {
    
     visitor->visitConcreteElementB(this); }
};

// 具体访问者
class ConcreteVisitor1 : public Visitor {
    
    
public:
  void visitConcreteElementA(ConcreteElementA* element) override {
    
     /* ... */ }
  void visitConcreteElementB(ConcreteElementB* element) override {
    
     /* ... */ }
};

class ConcreteVisitor2 : public Visitor {
    
    
public:
  void visitConcreteElementA(ConcreteElementA* element) override {
    
     /* ... */ }
  void visitConcreteElementB(ConcreteElementB* element) override {
    
     /* ... */ }
};

C++设计模式区别及应用

设计模式之间最大的区别在于它们解决的问题和应用场景不同。创建型模式关注对象的创建,结构型模式关注对象的组合,行为型模式关注对象之间的交互。

选择合适的设计模式需要根据具体问题进行分析,没有一种模式适用于所有情况。

模式 分类 意图 应用场景 区别
单例模式 (Singleton) 创建型 保证一个类只有一个实例,并提供一个全局访问点。 数据库连接池、日志记录器、配置文件读取器 与其他创建型模式不同,它只关注单个实例的创建和访问。
工厂方法模式 (Factory Method) 创建型 定义一个创建对象的接口,但由子类决定实例化哪个类。 当一个类无法预料要创建哪种对象,或需要将对象的创建委托给子类时。 与抽象工厂模式相比,它只关注单个产品的创建,而不是一系列相关产品。
抽象工厂模式 (Abstract Factory) 创建型 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。 当需要创建一系列相关产品,且希望隐藏具体产品的创建细节时。 与工厂方法模式相比,它关注一系列相关产品的创建。
建造者模式 (Builder) 创建型 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。 当一个对象的创建过程较为复杂,包含多个步骤,且希望将构建过程与表示分离时。 与工厂模式相比,它更注重构建过程的灵活性,可以逐步构建对象。
原型模式 (Prototype) 创建型 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 当创建对象的成本较高,或希望避免重复创建相同对象时。 与其他创建型模式不同,它通过拷贝原型对象来创建新对象。
适配器模式 (Adapter) 结构型 将一个类的接口转换成客户端所期望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 当需要使用一个已存在的类,但其接口与当前系统的接口不兼容时。 与桥接模式相比,它更注重接口的转换,而不是抽象与实现的分离。
桥接模式 (Bridge) 结构型 将抽象部分与它的实现部分分离,使它们都可以独立地变化。 当需要将抽象与实现分离,使其可以独立变化时。 与适配器模式相比,它更注重抽象与实现的分离,而不是接口的转换。
组合模式 (Composite) 结构型 将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 当需要表示对象的层次结构,且希望用户能够以相同的方式处理单个对象和组合对象时。 与装饰器模式相比,它更注重对象的组合,而不是动态地添加功能。
装饰器模式 (Decorator) 结构型 动态地给一个对象添加一些额外的职责。就扩展功能而言,它比生成子类方式更为灵活。 当需要动态地给一个对象添加功能,且不希望通过继承来实现时。 与组合模式相比,它更注重动态地添加功能,而不是对象的组合。
外观模式 (Facade) 结构型 为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 当需要简化一个复杂子系统的使用,或隐藏子系统的内部细节时。 与适配器模式相比,它更注重简化接口,而不是转换接口。
享元模式 (Flyweight) 结构型 运用共享技术有效地支持大量细粒度的对象。 当需要创建大量细粒度的对象,且这些对象大部分属性相同,只有少量属性不同时。 与其他结构型模式不同,它更注重对象的共享,以节省内存和提高性能。
代理模式 (Proxy) 结构型 为其他对象提供一种代理以控制对这个对象的访问。 当需要控制对一个对象的访问,或延迟对象的创建时。 与适配器模式相比,它更注重控制对象的访问,而不是转换接口。
责任链模式 (Chain of Responsibility) 行为型 为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。 当需要将请求的处理者与发送者解耦,或希望多个对象都有机会处理请求时。 与命令模式相比,它更注重请求的传递,而不是请求的封装。
命令模式 (Command) 行为型 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 当需要将请求封装成对象,以便参数化、排队、记录日志或支持撤销操作时。 与责任链模式相比,它更注重请求的封装,而不是请求的传递。
解释器模式 (Interpreter) 行为型 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 当需要解释一种简单的语言,或希望将语言的解释与应用逻辑分离时。 与其他行为型模式不同,它更注重语言的解释。
迭代器模式 (Iterator) 行为型 提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。 当需要顺序访问一个聚合对象中的元素,且不希望暴露该对象的内部表示时。 与其他行为型模式不同,它更注重对聚合对象的遍历。
中介者模式 (Mediator) 行为型 用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。 当多个对象之间存在复杂的交互关系,且希望降低对象之间的耦合度时。 与观察者模式相比,它更注重对象之间的交互,而不是事件的通知。
备忘录模式 (Memento) 行为型 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 当需要保存一个对象的内部状态,以便以后恢复时。 与其他行为型模式不同,它更注重对象的内部状态的保存和恢复。
观察者模式 (Observer) 行为型 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。 当一个对象的状态发生改变时,需要通知其他依赖于它的对象时。 与中介者模式相比,它更注重事件的通知,而不是对象之间的交互。
状态模式 (State) 行为型 允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。 当一个对象的行為取决于其内部状态,且需要在状态改变时改变其行为时。 与策略模式相比,它更注重状态的改变,而不是算法的选择。
策略模式 (Strategy) 行为型 定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。 当需要在运行时选择不同的算法,或希望将算法的实现与使用分离时。 与状态模式相比,它更注重算法的选择,而不是状态的改变。
模板方法模式 (Template Method) 行为型 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 当需要定义一个算法的骨架,并将一些步骤延迟到子类中实现时。 与策略模式相比,它更注重算法结构的定义,而不是算法的具体实现。
访问者模式 (Visitor) 行为型 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 当需要对一个对象结构中的元素执行不同的操作,且不希望修改元素的类时。 与其他行为型模式不同,它更注重对对象结构的访问和操作。

注意:

  • 以上表格只是对 23 种设计模式的简要概括,每种模式都有其自身的特点和适用场景,需要根据具体情况选择合适的模式。
  • 在实际应用中,可以组合使用多种设计模式来解决复杂的问题。

猜你喜欢

转载自blog.csdn.net/weixin_40514381/article/details/142846878