23种设计模式_Modern C++
设计原则:
单一职责原则(SRP):一个类应该仅有一个引起它变化的原因;变化的方向隐含着类的责任。
开放封闭原则(OCP):对扩展开放,对更改封闭;类模块应该是可扩展的,但是不可修改。
里氏替换原则(LSP):子类必须能够替换它们的基类(IS - A);继承表达类型抽象。
接口隔离原则(ISP):不应该强迫客户程序依赖它们不用的方法;接口应该小而完备。
依赖倒置原则(DIP):高层模块不应该依赖于低层模块,二者应该依赖于抽象;抽象不应该依赖于实现细节,实现细节依赖于抽象。
优先使用对象组合而不是继承:子类父类耦合度高,在一定程度上破坏了封装性。
面向接口编程:减少系统中各部分的依赖关系,实现”高内聚,松耦合“的设计方案。
封装变化点:让设计者在一层进行修改,而不影响其它层次的代码。实现层次间的松耦合。
创建型模式 (Creational Patterns):
1. 单例模式 (Singleton)
-
GOF定义:
- 确保一个类只有一个实例,并提供一个全局访问点。
-
动机:
- 保证一个类只有一个实例并且这个实例易于被访问。
-
类图
- 时序图
- 代码
#include <iostream>
class Singleton {
private:
// 私有构造函数,防止外部直接创建对象
Singleton() {}
public:
// 删除拷贝构造函数和赋值操作符,防止复制实例
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 公有静态方法,用于获取类的唯一实例
static Singleton* getInstance() {
static Singleton instance;
return &instance;
}
// 示例方法,用于展示单例的功能
void doSomething() {
std::cout << "Doing something..." << std::endl;
}
};
// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;
// 客户端代码
int main() {
// 获取单例对象并调用方法
Singleton* singleton = Singleton::getInstance();
singleton->doSomething();
return 0;
}
2. 工厂方法模式 (Factory Method)
-
GOF定义:
- 定义一个用于创建对象的接口,让子类决定实例化哪一个类。
-
动机:
- 在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。
- 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合?
-
类图
- 时序图
- 代码
#include <iostream>
#include <memory>
// 抽象产品类
class Product {
public:
virtual ~Product() {}
virtual std::string Use() const = 0;
};
// 具体产品类A
class ConcreteProductA : public Product {
public:
std::string Use() const override {
return "使用产品A";
}
};
// 具体产品类B
class ConcreteProductB : public Product {
public:
std::string Use() const override {
return "使用产品B";
}
};
// 抽象工厂类
class Creator {
public:
virtual ~Creator() {}
virtual std::unique_ptr<Product> FactoryMethod() const = 0;
};
// 具体工厂类A
class ConcreteCreatorA : public Creator {
public:
std::unique_ptr<Product> FactoryMethod() const override {
return std::make_unique<ConcreteProductA>();
}
};
// 具体工厂类B
class ConcreteCreatorB : public Creator {
public:
std::unique_ptr<Product> FactoryMethod() const override {
return std::make_unique<ConcreteProductB>();
}
};
// 客户端代码
void ClientCode(const Creator& creator) {
auto product = creator.FactoryMethod();
std::cout << product->Use() << std::endl;
}
int main() {
ConcreteCreatorA creatorA;
ClientCode(creatorA);
ConcreteCreatorB creatorB;
ClientCode(creatorB);
}
3. 抽象工厂模式 (Abstract Factory)
-
GOF定义:
- 提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
-
动机:
- 为了更清晰地理解工厂方法模式,需要先引入两个概念:
- 产品等级结构 :产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
- 产品族 :在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。
- 当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式。
- 为了更清晰地理解工厂方法模式,需要先引入两个概念:
-
类图
- 时序图
- 代码
#include <iostream>
#include <memory>
// 抽象产品A和B
class AbstractProductA {
public:
virtual ~AbstractProductA() {}
virtual std::string UsefulFunctionA() const = 0;
};
class AbstractProductB {
public:
virtual ~AbstractProductB() {}
virtual std::string UsefulFunctionB() const = 0;
};
// 具体产品A1和A2
class ConcreteProductA1 : public AbstractProductA {
public:
std::string UsefulFunctionA() const override {
return "The result of the product A1.";
}
};
class ConcreteProductA2 : public AbstractProductA {
public:
std::string UsefulFunctionA() const override {
return "The result of the product A2.";
}
};
// 具体产品B1和B2
class ConcreteProductB1 : public AbstractProductB {
public:
std::string UsefulFunctionB() const override {
return "The result of the product B1.";
}
};
class ConcreteProductB2 : public AbstractProductB {
public:
std::string UsefulFunctionB() const override {
return "The result of the product B2.";
}
};
// 抽象工厂
class AbstractFactory {
public:
virtual ~AbstractFactory() {}
virtual std::unique_ptr<AbstractProductA> CreateProductA() const = 0;
virtual std::unique_ptr<AbstractProductB> CreateProductB() const = 0;
};
// 具体工厂1和2
class ConcreteFactory1 : public AbstractFactory {
public:
std::unique_ptr<AbstractProductA> CreateProductA() const override {
return std::make_unique<ConcreteProductA1>();
}
std::unique_ptr<AbstractProductB> CreateProductB() const override {
return std::make_unique<ConcreteProductB1>();
}
};
class ConcreteFactory2 : public AbstractFactory {
public:
std::unique_ptr<AbstractProductA> CreateProductA() const override {
return std::make_unique<ConcreteProductA2>();
}
std::unique_ptr<AbstractProductB> CreateProductB() const override {
return std::make_unique<ConcreteProductB2>();
}
};
// 客户端代码
void ClientCode(const AbstractFactory &factory) {
auto productA = factory.CreateProductA();
auto productB = factory.CreateProductB();
std::cout << productA->UsefulFunctionA() << std::endl;
std::cout << productB->UsefulFunctionB() << std::endl;
}
int main() {
std::cout << "Client: Testing client code with the first factory type:\n";
ConcreteFactory1 factory1;
ClientCode(factory1);
std::cout << "\nClient: Testing the same client code with the second factory type:\n";
ConcreteFactory2 factory2;
ClientCode(factory2);
}
4. 建造者模式 (Builder)
-
GOF定义:
- 将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同的表示(变化)。
-
动机:
- 在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这 个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
- 如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?
-
类图
- 时序图
- 代码
#include <iostream>
#include <string>
// 产品类
class Product {
public:
// 一系列用于添加部件的方法
void AddPart(const std::string& part) {
parts_.push_back(part);
}
void ShowProduct() const {
std::cout << "Product parts: ";
for (const auto& part : parts_) {
std::cout << part << ", ";
}
std::cout << "\b\b " << std::endl; // 删除最后的逗号和空格
}
private:
std::vector<std::string> parts_;
};
// 抽象建造者类
class Builder {
public:
virtual ~Builder() {}
virtual void BuildPartA() const = 0;
virtual void BuildPartB() const = 0;
virtual void BuildPartC() const = 0;
virtual Product* GetProduct() = 0;
};
// 具体建造者类
class ConcreteBuilder : public Builder {
public:
ConcreteBuilder() {
Reset();
}
~ConcreteBuilder() {
delete product_;
}
void Reset() {
if (product_ != nullptr) {
delete product_;
}
product_ = new Product();
}
void BuildPartA() const override {
product_->AddPart("PartA");
}
void BuildPartB() const override {
product_->AddPart("PartB");
}
void BuildPartC() const override {
product_->AddPart("PartC");
}
Product* GetProduct() override {
Product* result = product_;
Reset();
return result;
}
private:
Product* product_;
};
// 指挥者类
class Director {
public:
void SetBuilder(Builder* builder) {
builder_ = builder;
}
// 构建最小特征的产品
void BuildMinimalViableProduct() {
builder_->BuildPartA();
}
// 构建完整特征的产品
void BuildFullFeaturedProduct() {
builder_->BuildPartA();
builder_->BuildPartB();
builder_->BuildPartC();
}
private:
Builder* builder_;
};
// 客户端代码
int main() {
Director* director = new Director();
ConcreteBuilder* builder = new ConcreteBuilder();
director->SetBuilder(builder);
// 构建最小特征的产品
std::cout << "Standard basic product:" << std::endl;
director->BuildMinimalViableProduct();
Product* p = builder->GetProduct();
p->ShowProduct();
delete p;
// 构建完整特征的产品
std::cout << "Standard full featured product:" << std::endl;
director->BuildFullFeaturedProduct();
p = builder->GetProduct();
p->ShowProduct();
delete p;
delete director;
delete builder;
return 0;
}
5. 原型模式 (Prototype)
-
GOF定义:
- 使用原型实例指定创建对象的种类,然后通过拷贝这些原型来创建新的对象。
-
动机:
- 在软件系统中,经常面临这“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。
- 如何应对这种变化?如何向“客户程序(使用这些对象的程序)”隔离出“这些易变对象”,从而使得依赖这些”易变对象“的客户程序不随着需求改变而改变。
-
类图
- 代码
#include <iostream>
#include <unordered_map>
#include <string>
#include <memory>
// “Prototype”基类
class Prototype {
public:
virtual ~Prototype() {}
virtual std::unique_ptr<Prototype> clone() const = 0;
virtual void execute() const = 0;
};
// 具体的原型类
class ConcretePrototypeA : public Prototype {
private:
std::string exampleState;
public:
ConcretePrototypeA(const std::string& state) : exampleState(state) {}
std::unique_ptr<Prototype> clone() const override {
return std::make_unique<ConcretePrototypeA>(*this);
}
void execute() const override {
std::cout << "ConcretePrototypeA state: " << exampleState << std::endl;
}
};
// 另一个具体的原型类
class ConcretePrototypeB : public Prototype {
private:
std::string exampleState;
public:
ConcretePrototypeB(const std::string& state) : exampleState(state) {}
std::unique_ptr<Prototype> clone() const override {
return std::make_unique<ConcretePrototypeB>(*this);
}
void execute() const override {
std::cout << "ConcretePrototypeB state: " << exampleState << std::endl;
}
};
// 客户端代码
int main() {
std::unordered_map<std::string, std::unique_ptr<Prototype>> prototypes;
prototypes["A"] = std::make_unique<ConcretePrototypeA>("A-state");
prototypes["B"] = std::make_unique<ConcretePrototypeB>("B-state");
// 假设我们需要一个“B”的副本
std::unique_ptr<Prototype> clonedPrototype = prototypes["B"]->clone();
clonedPrototype->execute();
return 0;
}
结构型模式 (Structural Patterns):
6. 适配器模式 (Adapter)
-
GOF定义:
- 将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
-
动机:
- 由于应用环境的变化,常常需要将”一些现存的对象“放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足。
- 如何应对这些”迁移的变化“?
-
对象适配器类图
- 类适配器类图
- 时序图
- 代码
#include <iostream>
#include <algorithm>
// “目标”接口定义了客户端使用的与特定领域相关的接口
class Target {
public:
virtual ~Target() = default;
virtual std::string Request() const {
return "Target: The default target's behavior.";
}
};
// “被适配者”包含一些有用的行为,但其接口与现有的客户端代码不兼容
class Adaptee {
public:
std::string SpecificRequest() const {
return ".eetpadA eht fo roivaheb laicepS";
}
};
// “适配器”使Adaptee的接口与Target的接口兼容
class Adapter : public Target {
private:
Adaptee *adaptee_;
public:
Adapter(Adaptee *adaptee) : adaptee_(adaptee) {}
std::string Request() const override {
std::string to_reverse = adaptee_->SpecificRequest();
std::reverse(to_reverse.begin(), to_reverse.end());
return "Adapter: (TRANSLATED) " + to_reverse;
}
};
// 客户端代码支持所有遵循Target接口的类
void ClientCode(const Target *target) {
std::cout << target->Request();
}
int main() {
std::cout << "Client: I can work just fine with the Target objects:\n";
Target *target = new Target;
ClientCode(target);
std::cout << "\n\n";
Adaptee *adaptee = new Adaptee;
std::cout << "Client: The Adaptee class has a weird interface. See, I don't understand it:\n";
std::cout << "Adaptee: " << adaptee->SpecificRequest();
std::cout << "\n\n";
std::cout << "Client: But I can work with it via the Adapter:\n";
Adapter *adapter = new Adapter(adaptee);
ClientCode(adapter);
std::cout << "\n";
delete target;
delete adaptee;
delete adapter;
return 0;
}
7. 桥接模式 (Bridge)
-
GOF定义:
- 将抽象部分(业务功能)与实现部分(平台实现)分离,使它们都可以独立地变化。
-
动机:
- 由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个纬度的变化。
- 如何应对这种“多维度的变化”?如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化,而不引入额外的复杂度?
- 类图
- 时序图
- 代码
#include <iostream>
#include <memory>
// 实现接口
class Implementor {
public:
virtual ~Implementor() {}
virtual void operationImp() const = 0;
};
// 具体实现A
class ConcreteImplementorA : public Implementor {
public:
void operationImp() const override {
std::cout << "ConcreteImplementorA Operation" << std::endl;
}
};
// 具体实现B
class ConcreteImplementorB : public Implementor {
public:
void operationImp() const override {
std::cout << "ConcreteImplementorB Operation" << std::endl;
}
};
// 抽象
class Abstraction {
protected:
std::unique_ptr<Implementor> implementor;
public:
Abstraction(std::unique_ptr<Implementor> imp) : implementor(std::move(imp)) {}
virtual ~Abstraction() {}
virtual void operation() const {
implementor->operationImp();
}
};
// 扩展抽象
class RefinedAbstraction : public Abstraction {
public:
RefinedAbstraction(std::unique_ptr<Implementor> imp) : Abstraction(std::move(imp)) {}
void operation() const override {
std::cout << "RefinedAbstraction: ";
implementor->operationImp();
}
};
// 客户端代码
int main() {
std::unique_ptr<Implementor> concreteImplementorA = std::make_unique<ConcreteImplementorA>();
std::unique_ptr<Abstraction> abstraction = std::make_unique<RefinedAbstraction>(std::move(concreteImplementorA));
abstraction->operation();
std::unique_ptr<Implementor> concreteImplementorB = std::make_unique<ConcreteImplementorB>();
abstraction = std::make_unique<RefinedAbstraction>(std::move(concreteImplementorB));
abstraction->operation();
return 0;
}
8. 组合模式 (Composite)
-
GOF定义:
- 将对象组合成树形结构以表示”部分-整体“的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性(稳定)。
-
动机:
- 客户代码过多地依赖于对象容器复杂的内部实现结构,对象容器内部实现结构(而非抽象结构)的变化 引起客户代码的频繁变化,带来了代码的维护性、扩展性等弊端。
- 如何将”客户代码与复杂的对象容器结构“解耦?让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂的对象容器?
-
类图1
- 类图2
- 代码
#include <iostream>
#include <vector>
#include <memory>
// "Component"类声明了所有具体类共有的接口
class Component {
protected:
Component *parent_;
public:
virtual ~Component() {}
void SetParent(Component *parent) {
this->parent_ = parent;
}
Component *GetParent() const {
return this->parent_;
}
// 添加和移除树枝或叶子
virtual void Add(std::shared_ptr<Component> component) {}
virtual void Remove(std::shared_ptr<Component> component) {}
// 可以提供一些默认的行为或全部留给具体类去实现
virtual bool IsComposite() const {
return false;
}
virtual std::string Operation() const = 0;
};
// "Leaf"类表示组合中的叶子对象,叶子没有子对象
class Leaf : public Component {
public:
std::string Operation() const override {
return "Leaf";
}
};
// "Composite"类表示组件可能有的分支节点,通常有子节点
class Composite : public Component {
private:
std::vector<std::shared_ptr<Component>> children_;
public:
void Add(std::shared_ptr<Component> component) override {
this->children_.push_back(component);
component->SetParent(this);
}
void Remove(std::shared_ptr<Component> component) override {
this->children_.erase(std::remove(this->children_.begin(), this->children_.end(), component), this->children_.end());
component->SetParent(nullptr);
}
bool IsComposite() const override {
return true;
}
std::string Operation() const override {
std::string result;
for (const std::shared_ptr<Component> &c : children_) {
if (c == children_.back()) {
result += c->Operation();
} else {
result += c->Operation() + "+";
}
}
return "Branch(" + result + ")";
}
};
// 客户端代码
void ClientCode(Component *component) {
std::cout << "RESULT: " << component->Operation();
}
// 更复杂的客户端代码,可以与组件的复合结构一起工作
void ClientCode2(Component *component1, Component *component2) {
if (component1->IsComposite()) {
component1->Add(std::make_shared<Leaf>());
}
std::cout << "RESULT: " << component1->Operation();
std::cout << "\n";
if (component2->IsComposite()) {
component2->Add(component1);
}
std::cout << "RESULT: " << component2->Operation();
}
int main() {
std::shared_ptr<Component> simple = std::make_shared<Leaf>();
std::cout << "Client: I've got a simple component:\n";
ClientCode(simple.get());
std::cout << "\n\n";
std::shared_ptr<Component> tree = std::make_shared<Composite>();
std::shared_ptr<Component> branch1 = std::make_shared<Composite>();
std::shared_ptr<Component> leaf_1 = std::make_shared<Leaf>();
std::shared_ptr<Component> leaf_2 = std::make_shared<Leaf>();
std::shared_ptr<Component> leaf_3 = std::make_shared<Leaf>();
branch1->Add(leaf_1);
branch1->Add(leaf_2);
tree->Add(branch1);
tree->Add(leaf_3);
std::cout << "Client: Now I've got a composite tree:\n";
ClientCode(tree.get());
std::cout << "\n\n";
std::cout << "Client: I don't need to check the components classes even when managing the tree:\n";
ClientCode2(tree.get(), simple.get());
std::cout << "\n";
}
9. 装饰器模式 (Decorator)
-
GOF定义:
- 动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类(继承)更为灵活(消除重复代码 & 减少子类个数)。
-
动机:
- 在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性; 并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。
- 如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?
- 类图
- 时序图
- 代码
#include <iostream>
#include <string>
// "Component"接口定义了所有具体组件和装饰器共有的操作
class Component {
public:
virtual ~Component() {}
virtual std::string Operation() const = 0;
};
// "ConcreteComponent"类实现了Component接口的操作
class ConcreteComponent : public Component {
public:
std::string Operation() const override {
return "ConcreteComponent";
}
};
// "Decorator"抽象类遵循与其他组件相同的接口
class Decorator : public Component {
protected:
Component* component_;
public:
Decorator(Component* component) : component_(component) {}
virtual std::string Operation() const override {
return component_->Operation();
}
};
// "ConcreteDecoratorA"类添加了一些功能
class ConcreteDecoratorA : public Decorator {
public:
ConcreteDecoratorA(Component* component) : Decorator(component) {}
std::string Operation() const override {
return "ConcreteDecoratorA(" + Decorator::Operation() + ")";
}
};
// "ConcreteDecoratorB"类也添加了一些功能
class ConcreteDecoratorB : public Decorator {
public:
ConcreteDecoratorB(Component* component) : Decorator(component) {}
std::string Operation() const override {
return "ConcreteDecoratorB(" + Decorator::Operation() + ")";
}
};
// 客户端代码可以使用Component接口与所有对象一起工作
void ClientCode(const Component* component) {
std::cout << "RESULT: " << component->Operation();
}
int main() {
Component* simple = new ConcreteComponent();
std::cout << "Client: I've got a simple component:\n";
ClientCode(simple);
std::cout << "\n\n";
Component* decorator1 = new ConcreteDecoratorA(simple);
Component* decorator2 = new ConcreteDecoratorB(decorator1);
std::cout << "Client: Now I've got a decorated component:\n";
ClientCode(decorator2);
std::cout << "\n";
delete simple;
delete decorator1;
delete decorator2;
return 0;
}
10. 外观模式 (Facade)
-
GOF定义:
- 为子系统中的一组接口提供一个一致(稳定)的界面,Façade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用(复用)。
-
动机:
- 客户和组件中各种复杂的子系统有过多的耦合
- 如何简化外部客户程序和系统间的交互接口?如何解耦?
- 类图
- 时序图
- 代码
#include <iostream>
// 子系统1
class Subsystem1 {
public:
void operation1() const {
std::cout << "Subsystem1: Ready!" << std::endl;
}
// ...
};
// 子系统2
class Subsystem2 {
public:
void operation2() const {
std::cout << "Subsystem2: Go!" << std::endl;
}
// ...
};
// 外观类
class Facade {
private:
Subsystem1 subsystem1;
Subsystem2 subsystem2;
public:
// 外观类可以与所有子系统的对象一起工作
Facade(Subsystem1 s1, Subsystem2 s2)
: subsystem1(s1), subsystem2(s2) {}
// 外观类提供了简单的方法来处理复杂的子系统操作
void operation() {
subsystem1.operation1();
subsystem2.operation2();
std::cout << "Facade: Operations completed." << std::endl;
}
};
// 客户端代码
int main() {
Subsystem1 subsystem1;
Subsystem2 subsystem2;
Facade facade(subsystem1, subsystem2);
facade.operation();
return 0;
}
11. 享元模式 (Flyweight)
-
GOF定义:
- 运行共享技术有效地支持大量细粒度的对象。。
-
动机:
- 在软件系统采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价——主要指内存需求方面的代价。
- 如何在避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象的方式来进行操作?
- 类图
- 时序图
- 代码
#include <iostream>
#include <map>
#include <memory>
#include <string>
// 抽象享元类
class Flyweight {
public:
virtual ~Flyweight() {}
virtual void Operation(const std::string& extrinsicState) const = 0;
};
// 具体享元类
class ConcreteFlyweight : public Flyweight {
private:
std::string intrinsicState;
public:
ConcreteFlyweight(const std::string& state) : intrinsicState(state) {}
void Operation(const std::string& extrinsicState) const override {
std::cout << "ConcreteFlyweight: Intrinsic State = " << intrinsicState
<< ", Extrinsic State = " << extrinsicState << std::endl;
}
};
// 享元工厂类
class FlyweightFactory {
private:
std::map<std::string, std::shared_ptr<Flyweight>> flyweights;
public:
std::shared_ptr<Flyweight> GetFlyweight(const std::string& key) {
if (flyweights.find(key) == flyweights.end()) {
flyweights[key] = std::make_shared<ConcreteFlyweight>(key);
}
return flyweights[key];
}
};
// 客户端代码
int main() {
FlyweightFactory factory;
auto flyweight = factory.GetFlyweight("sharedState");
flyweight->Operation("extrinsicState1");
auto flyweight2 = factory.GetFlyweight("sharedState");
flyweight2->Operation("extrinsicState2");
return 0;
}
12. 代理模式 (Proxy)
-
GOF定义:
- 为其他对象提供一种代理以控制(隔离,使用接口)对这对象的访问。
-
动机:
- 在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等), 直接访问会给使用者、或者系统结构带来很多麻烦。
- 如何在不失去透明操作对象的同事来管理/控制这些对象特有的复杂性?增加一层间接层是软件开发中常见的解决方式。
- 类图
- 时序图
- 代码
#include <iostream>
#include <memory>
// 抽象主题接口
class Subject {
public:
virtual ~Subject() {}
virtual void request() const = 0;
};
// 真实主题类
class RealSubject : public Subject {
public:
void request() const override {
std::cout << "RealSubject: Handling request." << std::endl;
}
};
// 代理类
class Proxy : public Subject {
private:
std::unique_ptr<RealSubject> realSubject;
bool checkAccess() const {
// 模拟访问控制
std::cout << "Proxy: Checking access prior to firing a real request." << std::endl;
// 模拟访问控制逻辑,这里简单返回true
return true;
}
void logAccess() const {
// 记录请求日志
std::cout << "Proxy: Logging the time of request." << std::endl;
}
public:
Proxy(std::unique_ptr<RealSubject> realSubject) : realSubject(std::move(realSubject)) {}
void request() const override {
if (this->checkAccess()) {
this->realSubject->request();
this->logAccess();
}
}
};
// 客户端代码
int main() {
std::unique_ptr<RealSubject> realSubject = std::make_unique<RealSubject>();
Proxy proxy(std::move(realSubject));
proxy.request();
return 0;
}
行为型模式 (Behavioral Patterns):
13. 责任链模式 (Chain of Responsibility)
-
GOF定义:
- 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
-
动机:
- 一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接收者,如果显式指定,将必不可少地带来请求发送者与接收者的紧耦合。
- 如何使请求的发送者不需要指定具体的接收者?让请求的接收者自己在运行时决定来处理请求,从而使两者解耦。
- 类图
- 示意图
- 代码
#include <iostream>
#include <memory>
// "Handler"接口声明了构建处理链的方法,以及执行请求的方法
class Handler {
protected:
std::shared_ptr<Handler> successor_;
public:
virtual ~Handler() {}
void SetSuccessor(std::shared_ptr<Handler> successor) {
successor_ = successor;
}
virtual void HandleRequest(const std::string& request) = 0;
};
// "ConcreteHandler1"类实现了处理请求的方法
class ConcreteHandler1 : public Handler {
public:
void HandleRequest(const std::string& request) override {
if (request == "Request1") {
std::cout << "ConcreteHandler1 handled the request: " << request << std::endl;
} else if (successor_) {
successor_->HandleRequest(request);
}
}
};
// "ConcreteHandler2"类也实现了处理请求的方法
class ConcreteHandler2 : public Handler {
public:
void HandleRequest(const std::string& request) override {
if (request == "Request2") {
std::cout << "ConcreteHandler2 handled the request: " << request << std::endl;
} else if (successor_) {
successor_->HandleRequest(request);
}
}
};
// 客户端代码
int main() {
std::shared_ptr<Handler> handler1 = std::make_shared<ConcreteHandler1>();
std::shared_ptr<Handler> handler2 = std::make_shared<ConcreteHandler2>();
handler1->SetSuccessor(handler2);
handler1->HandleRequest("Request1");
handler1->HandleRequest("Request2");
return 0;
}
14. 命令模式 (Command)
-
GOF定义:
- 将一个请求(行为)封装成一个对象,从而使你可用不用的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
-
动机:
- Command模式的根本目的在于将”行为请求者“与”行为实现者“解耦,在面向对象语言中,常见的实现手段是”将行为抽象为对象“。
- 与C++中的函数对象类似,C++函数对象以函数签名来定义行为接口规范,更灵活性能更高。
- 类图
- 时序图
- 代码
#include <iostream>
#include <vector>
#include <memory>
// 命令接口
class Command {
public:
virtual ~Command() {}
virtual void execute() = 0;
};
// 接收者类
class Receiver {
public:
void performAction() {
std::cout << "Receiver: Execute action." << std::endl;
}
};
// 具体命令类
class ConcreteCommand : public Command {
private:
Receiver* receiver;
public:
ConcreteCommand(Receiver* r) : receiver(r) {}
void execute() override {
if (receiver) {
receiver->performAction();
}
}
};
// 调用者类
class Invoker {
private:
std::vector<std::unique_ptr<Command>> commands;
public:
void addCommand(std::unique_ptr<Command> command) {
commands.push_back(std::move(command));
}
void executeCommands() {
for (auto& cmd : commands) {
if (cmd) {
cmd->execute();
}
}
}
};
// 客户端代码
int main() {
Receiver receiver;
Invoker invoker;
// 创建命令并添加到调用者
invoker.addCommand(std::make_unique<ConcreteCommand>(&receiver));
invoker.addCommand(std::make_unique<ConcreteCommand>(&receiver));
// 执行所有命令
invoker.executeCommands();
return 0;
}
15. 解释器模式 (Interpreter)
-
GOF定义:
- 给定一个语言,定义它的文法的一种表示,并定义一种解释器,这个解释器使用该表示来解释语言中的句子。
-
动机:
- 如果某一特定领域的问题比较复杂,类似的结构不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化。
- 在这种情况下,将特定领域的问题表达为某种语法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的。
- 类图
- 示意图
- 代码
#include <iostream>
#include <vector>
#include <memory>
// 命令接口
class Command {
public:
virtual ~Command() {}
virtual void execute() = 0;
};
// 接收者类
class Receiver {
public:
void performAction() {
std::cout << "Receiver: Execute action." << std::endl;
}
};
// 具体命令类
class ConcreteCommand : public Command {
private:
Receiver* receiver;
public:
ConcreteCommand(Receiver* r) : receiver(r) {}
void execute() override {
if (receiver) {
receiver->performAction();
}
}
};
// 调用者类
class Invoker {
private:
std::vector<std::unique_ptr<Command>> commands;
public:
void addCommand(std::unique_ptr<Command> command) {
commands.push_back(std::move(command));
}
void executeCommands() {
for (auto& cmd : commands) {
if (cmd) {
cmd->execute();
}
}
}
};
// 客户端代码
int main() {
Receiver receiver;
Invoker invoker;
// 创建命令并添加到调用者
invoker.addCommand(std::make_unique<ConcreteCommand>(&receiver));
invoker.addCommand(std::make_unique<ConcreteCommand>(&receiver));
// 执行所有命令
invoker.executeCommands();
return 0;
}
16. 迭代器模式 (Iterator)
-
GOF定义:
- 提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露(稳定)该对象的内部表示。
-
动机:
- 集合对象内部结构常常变化异常。但对于这些集合对象,我们希望不暴露其内部结构的同时,可以让外部客户代码透明地访问其中包含的元素; 同时这种”透明遍历“也为”同一种算法在多种集合对象上进行操作“提供了可能。
- 使用面向对象技术将这种遍历机制抽象为”迭代器对象“为”应对变化中的集合对象“提供了一种优雅的方式。
-
类图
- 代码
#include <iostream>
#include <vector>
// 迭代器抽象基类
template <typename T>
class Iterator {
public:
virtual ~Iterator() {}
virtual T& next() = 0;
virtual bool hasNext() const = 0;
};
// 具体聚合类
template <typename T>
class ConcreteAggregate {
private:
std::vector<T> data;
public:
void add(const T& item) {
data.push_back(item);
}
// 具体迭代器类
class ConcreteIterator : public Iterator<T> {
private:
ConcreteAggregate<T>& aggregate;
size_t index;
public:
ConcreteIterator(ConcreteAggregate<T>& agg) : aggregate(agg), index(0) {}
T& next() override {
return aggregate.data[index++];
}
bool hasNext() const override {
return index < aggregate.data.size();
}
};
// 创建迭代器的方法
ConcreteIterator createIterator() {
return ConcreteIterator(*this);
}
};
// 客户端代码
int main() {
ConcreteAggregate<int> aggregate;
aggregate.add(1);
aggregate.add(2);
aggregate.add(3);
auto iterator = aggregate.createIterator();
while (iterator.hasNext()) {
std::cout << iterator.next() << std::endl;
}
return 0;
}
17. 中介者模式 (Mediator)
-
GOF定义:
- 用一个中介对象来封装(封装变化)一系列的对象交互。中介者使各对象不需要显式的相互引用(编译时依赖->运行时依赖), 从而使其耦合松散(管理变化),并且可以独立地改变它们之间的交互。
-
动机:
- 多个对象相互关联的情况,对象之间常常会维持一种复杂的引用关系,如果遇到一些需求的更改,这种直接的引用关系将面临不断的变化。
- 在这种情况下,可以使用一种”中介对象“来管理对象间的关联关系,避免相互交互的对象之间的紧耦合引用关系,从而更好地抵御变化。
- 类图
- 时序图
- 代码
#include <iostream>
#include <string>
#include <map>
// 中介者接口
class Mediator {
public:
virtual void Notify(const std::string& sender, const std::string& event) = 0;
};
// 同事类的基类
class BaseComponent {
protected:
Mediator* mediator_;
public:
BaseComponent(Mediator* mediator = nullptr) : mediator_(mediator) {}
void set_mediator(Mediator* mediator) {
mediator_ = mediator;
}
};
// 具体同事类
class Component1 : public BaseComponent {
public:
void DoA() {
std::cout << "Component 1 does A.\n";
mediator_->Notify("Component1", "A");
}
void DoB() {
std::cout << "Component 1 does B.\n";
mediator_->Notify("Component1", "B");
}
};
class Component2 : public BaseComponent {
public:
void DoC() {
std::cout << "Component 2 does C.\n";
mediator_->Notify("Component2", "C");
}
void DoD() {
std::cout << "Component 2 does D.\n";
mediator_->Notify("Component2", "D");
}
};
// 具体中介者
class ConcreteMediator : public Mediator {
private:
Component1* component1_;
Component2* component2_;
public:
ConcreteMediator(Component1* c1, Component2* c2) : component1_(c1), component2_(c2) {
component1_->set_mediator(this);
component2_->set_mediator(this);
}
void Notify(const std::string& sender, const std::string& event) override {
if (event == "A") {
std::cout << "Mediator reacts on A and triggers following operations:\n";
component2_->DoC();
} else if (event == "D") {
std::cout << "Mediator reacts on D and triggers following operations:\n";
component1_->DoB();
component2_->DoC();
}
}
};
// 客户端代码
void ClientCode() {
Component1* c1 = new Component1;
Component2* c2 = new Component2;
ConcreteMediator* mediator = new ConcreteMediator(c1, c2);
std::cout << "Client triggers operation A.\n";
c1->DoA();
std::cout << "\nClient triggers operation D.\n";
c2->DoD();
delete c1;
delete c2;
delete mediator;
}
int main() {
ClientCode();
return 0;
}
18. 备忘录模式 (Memento)
-
GOF定义:
- 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
-
动机:
- 某些对象的状态转换过程中,可能由于某中需要,要求程序能够回溯到对象之前处于某个点的状态。 如果使用一些公开接口来让其他对象得到对象的状态,便会暴露对象的细节实现。
- 如何实现对象状态的良好保存与恢复?但同时又不会因此而破坏对象本身的封装性。
- 类图
- 代码
#include <iostream>
#include <vector>
#include <string>
// 备忘录类
class Memento {
private:
std::string state;
public:
Memento(const std::string& stateToSave) : state(stateToSave) {}
std::string getState() const {
return state;
}
};
// 原发器类
class Originator {
private:
std::string state;
public:
void setState(const std::string& newState) {
state = newState;
}
std::string getState() const {
return state;
}
Memento saveStateToMemento() {
return Memento(state);
}
void restoreStateFromMemento(const Memento& memento) {
state = memento.getState();
}
};
// 管理者类
class Caretaker {
private:
std::vector<Memento> mementos;
public:
void addMemento(const Memento& memento) {
mementos.push_back(memento);
}
Memento getMemento(int index) const {
if (index >= 0 && index < mementos.size()) {
return mementos[index];
}
throw std::out_of_range("Invalid memento index");
}
};
// 客户端代码
int main() {
Originator originator;
Caretaker caretaker;
originator.setState("State #1");
caretaker.addMemento(originator.saveStateToMemento());
originator.setState("State #2");
caretaker.addMemento(originator.saveStateToMemento());
originator.setState("State #3");
originator.restoreStateFromMemento(caretaker.getMemento(0));
std::cout << "Current State: " << originator.getState() << std::endl;
return 0;
}
19. 观察者模式 (Observer)
-
GOF定义:
- 定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
-
动机:
- 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对 象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。
- 使用面向对象技术,可以将这种依赖关系弱化,并形成一种稳定的依赖关系。从而实现软件体系结构的松耦合。
- 类图
- 时序图
- 代码
#include <iostream>
#include <vector>
#include <string>
// 备忘录类
class Memento {
private:
std::string state;
public:
Memento(const std::string& stateToSave) : state(stateToSave) {}
std::string getState() const {
return state;
}
};
// 原发器类
class Originator {
private:
std::string state;
public:
void setState(const std::string& newState) {
state = newState;
}
std::string getState() const {
return state;
}
Memento saveStateToMemento() {
return Memento(state);
}
void restoreStateFromMemento(const Memento& memento) {
state = memento.getState();
}
};
// 管理者类
class Caretaker {
private:
std::vector<Memento> mementos;
public:
void addMemento(const Memento& memento) {
mementos.push_back(memento);
}
Memento getMemento(int index) const {
if (index >= 0 && index < mementos.size()) {
return mementos[index];
}
throw std::out_of_range("Invalid memento index");
}
};
// 客户端代码
int main() {
Originator originator;
Caretaker caretaker;
originator.setState("State #1");
caretaker.addMemento(originator.saveStateToMemento());
originator.setState("State #2");
caretaker.addMemento(originator.saveStateToMemento());
originator.setState("State #3");
originator.restoreStateFromMemento(caretaker.getMemento(0));
std::cout << "Current State: " << originator.getState() << std::endl;
return 0;
}
20. 状态模式 (State)
-
GOF定义:
- 允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。
-
动机:
- 对象状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。
- 如何在运行时根据对象的状态来透明地改变对象的行为?
- 类图
- 时序图
- 代码
#include <iostream>
#include <memory>
class State;
class Context {
private:
std::unique_ptr<State> state_;
std::unique_ptr<State> nextState_;
public:
Context(std::unique_ptr<State> state) : state_(std::move(state)) {}
void TransitionTo(std::unique_ptr<State> state) {
nextState_ = std::move(state);
}
void Request();
void UpdateState() {
if (nextState_) {
state_ = std::move(nextState_);
std::cout << "Context: Transition to the new state.\n";
}
}
};
class State {
public:
virtual ~State() {}
virtual void Handle(Context* context) = 0;
};
class ConcreteStateA : public State {
public:
void Handle(Context* context) override {
std::cout << "State A handling context. Preparing to switch to State B.\n";
context->TransitionTo(std::make_unique<ConcreteStateB>());
}
};
class ConcreteStateB : public State {
public:
void Handle(Context* context) override {
std::cout << "State B handling context. Preparing to switch to State A.\n";
context->TransitionTo(std::make_unique<ConcreteStateA>());
}
};
void Context::Request() {
if (state_) {
state_->Handle(this);
UpdateState(); // Update the state after the handling is done
}
}
int main() {
auto context = std::make_unique<Context>(std::make_unique<ConcreteStateA>());
context->Request(); // State A handles and prepares to switch to State B
context->Request(); // State B handles and prepares to switch to State A
return 0;
}
21. 策略模式 (Strategy)
-
GOF定义:
- 定义一系列算法,把它们一个个封装起来,并且使它们可互相替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)。
-
动机:
- 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。
- 如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?
-
类图
- 时序图
- 代码
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
// 策略接口声明了所有支持的算法的公共操作
class Strategy {
public:
virtual ~Strategy() {}
virtual std::string DoAlgorithm(const std::vector<std::string>& data) const = 0;
};
// 具体策略实现了算法,同时遵循基础策略接口
// ConcreteStrategyA按正序排序
class ConcreteStrategyA : public Strategy {
public:
std::string DoAlgorithm(const std::vector<std::string>& data) const override {
std::string result;
std::vector<std::string> sortable = data;
std::sort(sortable.begin(), sortable.end());
for (const auto& element : sortable) {
result += element + " ";
}
return result;
}
};
// ConcreteStrategyB按逆序排序
class ConcreteStrategyB : public Strategy {
public:
std::string DoAlgorithm(const std::vector<std::string>& data) const override {
std::string result;
std::vector<std::string> sortable = data;
std::sort(sortable.begin(), sortable.end(), std::greater<>());
for (const auto& element : sortable) {
result += element + " ";
}
return result;
}
};
// 上下文定义了客户端感兴趣的接口
class Context {
private:
std::unique_ptr<Strategy> strategy_;
public:
explicit Context(std::unique_ptr<Strategy> strategy = nullptr) : strategy_(std::move(strategy)) {
}
void SetStrategy(std::unique_ptr<Strategy> strategy) {
strategy_ = std::move(strategy);
}
void DoSomeBusinessLogic() const {
if (strategy_) {
std::cout << "Context: Sorting data using the strategy (not sure how it'll do it)\n";
std::string result = strategy_->DoAlgorithm(std::vector<std::string>{"a", "e", "c", "b", "d"});
std::cout << result << "\n";
} else {
std::cout << "Context: Strategy isn't set\n";
}
}
};
// 客户端代码选择一个具体策略并将其传递给上下文
void ClientCode() {
Context context(std::make_unique<ConcreteStrategyA>());
std::cout << "Client: Strategy is set to normal sorting.\n";
context.DoSomeBusinessLogic();
std::cout << "\n";
std::cout << "Client: Strategy is set to reverse sorting.\n";
context.SetStrategy(std::make_unique<ConcreteStrategyB>());
context.DoSomeBusinessLogic();
}
int main() {
ClientCode();
return 0;
}
22. 模板方法模式 (Template Method)
-
GOF定义:
- 定义一个操作中的算法的骨架 (稳定) ,而将一些步骤延迟 (变化) 到子类中。 Template Method使得子类可以不改变(复用)一个算法的结构即可重定义(override 重写)该算法的 某些特定步骤。
-
动机:
- 在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体结构同时实现。
- 如何在确定稳定操作结构的前提下,来灵活应对各个子步骤的变化或者晚期实现需求?
-
类图
- 代码
#include <iostream>
// 抽象基类
class AbstractClass {
public:
// 模板方法,定义算法的骨架
void templateMethod() const {
this->baseOperation1();
this->requiredOperations1();
this->baseOperation2();
this->hook1();
this->requiredOperations2();
this->baseOperation3();
this->hook2();
}
protected:
void baseOperation1() const {
std::cout << "AbstractClass says: I am doing the bulk of the work\n";
}
void baseOperation2() const {
std::cout << "AbstractClass says: But I let subclasses override some operations\n";
}
void baseOperation3() const {
std::cout << "AbstractClass says: But I am doing the bulk of the work anyway\n";
}
// 纯虚函数,必须由子类实现
virtual void requiredOperations1() const = 0;
virtual void requiredOperations2() const = 0;
// 钩子函数,子类可以选择性重写
virtual void hook1() const {}
virtual void hook2() const {}
};
// 具体子类
class ConcreteClass1 : public AbstractClass {
protected:
void requiredOperations1() const override {
std::cout << "ConcreteClass1 says: Implemented Operation1\n";
}
void requiredOperations2() const override {
std::cout << "ConcreteClass1 says: Implemented Operation2\n";
}
};
// 另一个具体子类
class ConcreteClass2 : public AbstractClass {
protected:
void requiredOperations1() const override {
std::cout << "ConcreteClass2 says: Implemented Operation1\n";
}
void requiredOperations2() const override {
std::cout << "ConcreteClass2 says: Implemented Operation2\n";
}
void hook1() const override {
std::cout << "ConcreteClass2 says: Overridden Hook1\n";
}
};
// 客户端代码
int main() {
std::cout << "Same client code can work with different subclasses:\n";
ConcreteClass1 concreteClass1;
concreteClass1.templateMethod();
std::cout << "\n";
ConcreteClass2 concreteClass2;
concreteClass2.templateMethod();
return 0;
}
23. 访问者模式 (Visitor)
-
GOF定义:
- 表示一个作用与某对象结构中的各元素的操作。使得可以在不改变(稳定)各元素的类的前提下定义(扩展) 作用于这些元素的新操作(变化)。
-
动机:
- 由于需求的变化,某些类层次结构中常常需要增加新的行为(方法),如果直接在基类中做这样的更改, 将会给子类带来很繁重的变更负担,甚至破坏原有设计。
- 如何在不更改类层次结构的前提下,在运行时根据需要透明地为类层次结构上的各个类动态添加新的操作,从而避免上面的问题?
- 类图
- 时序图
- 代码
#include <iostream>
#include <vector>
// 访问者基类
class ConcreteComponentA;
class ConcreteComponentB;
class Visitor {
public:
virtual void VisitConcreteComponentA(const ConcreteComponentA* element) const = 0;
virtual void VisitConcreteComponentB(const ConcreteComponentB* element) const = 0;
};
// 元素基类
class Component {
public:
virtual ~Component() {}
virtual void Accept(Visitor* visitor) const = 0;
};
// 具体元素类A
class ConcreteComponentA : public Component {
public:
void Accept(Visitor* visitor) const override {
visitor->VisitConcreteComponentA(this);
}
std::string ExclusiveMethodOfConcreteComponentA() const {
return "A";
}
};
// 具体元素类B
class ConcreteComponentB : public Component {
public:
void Accept(Visitor* visitor) const override {
visitor->VisitConcreteComponentB(this);
}
std::string SpecialMethodOfConcreteComponentB() const {
return "B";
}
};
// 具体访问者类
class ConcreteVisitor1 : public Visitor {
public:
void VisitConcreteComponentA(const ConcreteComponentA* element) const override {
std::cout << element->ExclusiveMethodOfConcreteComponentA() << " + ConcreteVisitor1\n";
}
void VisitConcreteComponentB(const ConcreteComponentB* element) const override {
std::cout << element->SpecialMethodOfConcreteComponentB() << " + ConcreteVisitor1\n";
}
};
class ConcreteVisitor2 : public Visitor {
public:
void VisitConcreteComponentA(const ConcreteComponentA* element) const override {
std::cout << element->ExclusiveMethodOfConcreteComponentA() << " + ConcreteVisitor2\n";
}
void VisitConcreteComponentB(const ConcreteComponentB* element) const override {
std::cout << element->SpecialMethodOfConcreteComponentB() << " + ConcreteVisitor2\n";
}
};
// 客户端代码
void ClientCode(std::vector<const Component*> components, Visitor* visitor) {
for (const Component* comp : components) {
comp->Accept(visitor);
}
}
int main() {
std::vector<const Component*> components = {new ConcreteComponentA, new ConcreteComponentB};
ConcreteVisitor1* visitor1 = new ConcreteVisitor1;
ClientCode(components, visitor1);
ConcreteVisitor2* visitor2 = new ConcreteVisitor2;
ClientCode(components, visitor2);
for (const Component* comp : components) {
delete comp;
}
delete visitor1;
delete visitor2;
return 0;
}