设计模式
C++中常用的设计模式有很多,设计模式是解决常见问题的经过验证的最佳实践。以下是一些常用的设计模式:
- 单例模式(Singleton):确保一个类只有一个实例,并提供一个全局访问点。
- 工厂模式(Factory):用于创建对象,而不需要指定具体类。
- 抽象工厂模式(Abstract Factory):提供一组相关或相互依赖的对象,而不指定其具体类。
- 建造者模式(Builder):将一个复杂对象的构建与其表示分离,使相同的构建过程可以创建不同的表示。
- 原型模式(Prototype):通过克隆已有对象来创建新对象,以避免直接使用构造函数。
- 适配器模式(Adapter):将一个接口转换成另一个客户希望使用的接口。
- 装饰器模式(Decorator):动态地给一个对象添加一些额外的职责,而不需要子类化。
- 代理模式(Proxy):为其他对象提供一个代理以控制对这个对象的访问。
- 观察者模式(Observer):定义了一种一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知。
- 策略模式(Strategy):定义一系列算法,封装它们,使它们可以相互替换。
- 命令模式(Command):将一个请求封装成一个对象,从而允许使用不同的请求、队列或日志请求。
- 状态模式(State):允许对象在其内部状态改变时改变其行为。
- 模板方法模式(Template Method):定义算法的骨架,允许子类重写其中的步骤。
- 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
- 组合模式(Composite):将对象组合成树形结构以表示"部分-整体"的层次结构。
- 迭代器模式(Iterator):提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
- 中介者模式(Mediator):定义一个对象,封装一系列对象之间的交互,从而降低对象之间的耦合度。
- 备忘录模式(Memento):不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。
- 桥接模式(Bridge):将抽象部分与它的实现部分分离,使它们可以独立变化。
- 解释器模式(Interpreter):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
这些设计模式都有特定的应用场景,可以根据问题的性质选择合适的设计模式来解决。设计模式有助于提高代码的可维护性、可扩展性和复用性。
11.命令模式
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成一个对象,从而允许你参数化不同的请求、将请求排队、记录请求日志,或者支持可撤销的操作。命令模式的核心思想是将请求的发送者与请求的接收者解耦。
命令模式包含以下几个主要角色:
- 命令(Command) :命令是一个抽象类或接口,它定义了执行请求的方法
execute
。具体的命令类将实现这个接口,将请求参数绑定到接收者,并在execute
方法中执行具体的操作。 - 具体命令(Concrete Command):具体命令是命令接口的具体实现,它包括一个接收者对象,负责执行具体的操作。
- 接收者(Receiver):接收者是具体命令类的执行者,它包含了具体的业务逻辑,命令类将请求委派给接收者来执行。
- 调用者(Invoker):调用者是负责向命令对象发送请求的对象,它不需要了解命令是如何执行的,只需要将请求发送给命令对象。
命令模式的主要优点包括:
- 解耦命令发送者和命令执行者。
- 支持撤销和重做操作。
- 支持命令的组合,可以构建复杂的命令序列。
以下是一个简单的命令模式的 C++ 示例:
cpp
#include <iostream>
// 命令接口
class Command {
public:
virtual void execute() = 0;
};
// 具体命令
class LightOnCommand : public Command {
public:
LightOnCommand(Light& light) : light_(light) {}
void execute() override {
light_.on();
}
private:
Light& light_;
};
// 接收者
class Light {
public:
void on() {
std::cout << "Light is on" << std::endl;
}
void off() {
std::cout << "Light is off" << std::endl;
}
};
// 调用者
class RemoteControl {
public:
void setCommand(Command* command) {
command_ = command;
}
void pressButton() {
command_->execute();
}
private:
Command* command_;
};
int main() {
Light livingRoomLight;
LightOnCommand livingRoomLightOn(livingRoomLight);
RemoteControl remote;
remote.setCommand(&livingRoomLightOn);
remote.pressButton();
return 0;
}
在这个示例中,我们有一个命令接口 Command
,定义了 execute
方法。具体命令 LightOnCommand
包含一个接收者对象 Light
,在 execute
方法中调用接收者的方法。
调用者 RemoteControl
通过设置具体命令对象,并调用 pressButton
方法来执行命令。这种方式实现了调用者和接收者的解耦,调用者只需要知道如何发送命令,而不需要知道命令是如何执行的。
命令模式非常适用于构建可扩展和可维护的系统,特别是需要支持撤销、重做和构建复杂命令序列的情况。
12.状态模式
状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态改变时改变其行为。状态模式的核心思想是将不同状态抽象为独立的状态类,使对象能够在运行时切换不同状态,而不需要修改其代码。
状态模式包含以下几个主要角色:
- 上下文(Context):上下文类是包含状态的对象,它在运行时可以切换不同的状态对象。上下文类通常包括状态接口的引用,用于与当前状态进行交互。
- 状态(State):状态是一个抽象类或接口,它定义了一个特定状态的行为。具体的状态类将实现这个接口,每个状态类代表一个具体的状态,并定义了状态下的行为。
状态模式的主要优点包括:
- 将状态的行为封装在独立的状态类中,降低了上下文类的复杂性。
- 支持动态切换状态,使对象能够在运行时改变行为。
- 易于添加新的状态,同时不需要修改现有代码。
以下是一个简单的状态模式的 C++ 示例:
cpp
#include <iostream>
// 状态接口
class State {
public:
virtual void handle() = 0;
};
// 具体状态 A
class ConcreteStateA : public State {
public:
void handle() override {
std::cout << "Handling state A" << std::endl;
}
};
// 具体状态 B
class ConcreteStateB : public State {
public:
void handle() override {
std::cout << "Handling state B" << std::endl;
}
};
// 上下文
class Context {
public:
void setState(State* state) {
state_ = state;
}
void request() {
state_->handle();
}
private:
State* state_;
};
int main() {
ConcreteStateA stateA;
ConcreteStateB stateB;
Context context;
context.setState(&stateA);
context.request();
context.setState(&stateB);
context.request();
return 0;
}
在这个示例中,我们有一个状态接口 State
,定义了 handle
方法,具体状态类 ConcreteStateA
和 ConcreteStateB
分别实现了这个接口。
上下的 Context
包含一个状态对象的引用,它可以在运行时切换不同的状态。当调用 request
方法时,上下文对象会委托给当前状态对象来执行特定的行为。
状态模式使对象能够根据内部状态的改变而改变行为,这有助于消除大量的条件分支,提高了代码的可维护性和可扩展性。状态模式常用于处理对象的状态机、有限状态机、工作流等场景。
13.模板方法模式
模板方法模式(Template Method Pattern)是一种行为型设计模式,它定义了一组算法的骨架,将一些步骤延迟到子类实现。模板方法模式允许子类在不改变算法结构的情况下重新定义算法的某些步骤。
模板方法模式包含以下几个主要角色:
- 模板方法(Template Method):模板方法是一个抽象类,它定义了一个算法的骨架,包括一组步骤,其中一些步骤由子类实现。
- 具体模板(Concrete Template):具体模板类是模板方法的具体实现,它实现了模板方法中定义的具体步骤,其中一些步骤可能由子类实现。
模板方法模式的主要特点包括:
- 定义了一个算法的骨架,其中一些步骤延迟到子类实现。
- 子类可以重新定义模板方法中的特定步骤,以满足其特定需求,而无需改变算法的整体结构。
- 模板方法模式使得代码重用和扩展变得更加容易。
以下是一个简单的模板方法模式的 C++ 示例:
cpp
#include <iostream>
// 模板方法
class AbstractClass {
public:
// 模板方法定义了算法的骨架,包括一组步骤
void templateMethod() {
step1();
step2();
step3();
}
// 具体步骤由子类实现
virtual void step1() = 0;
virtual void step2() = 0;
virtual void step3() = 0;
};
// 具体模板
class ConcreteClassA : public AbstractClass {
public:
void step1() override {
std::cout << "ConcreteClassA - Step 1" << std::endl;
}
void step2() override {
std::cout << "ConcreteClassA - Step 2" << std::endl;
}
void step3() override {
std::cout << "ConcreteClassA - Step 3" << std::endl;
}
};
class ConcreteClassB : public AbstractClass {
public:
void step1() override {
std::cout << "ConcreteClassB - Step 1" << std::endl;
}
void step2() override {
std::cout << "ConcreteClassB - Step 2" << std::endl;
}
void step3() override {
std::cout << "ConcreteClassB - Step 3" << std::endl;
}
};
int main() {
ConcreteClassA a;
ConcreteClassB b;
a.templateMethod();
b.templateMethod();
return 0;
}
在这个示例中,我们有一个抽象类 AbstractClass
,它定义了一个模板方法 templateMethod
,包括一组步骤(step1
、step2
、step3
)。具体的步骤由子类实现。具体子类 ConcreteClassA
和 ConcreteClassB
分别实现了这些步骤。
当我们调用 templateMethod
时,模板方法会按照定义的算法骨架执行各个步骤。不同的子类可以重新定义这些步骤,以满足其特定需求。
模板方法模式非常适用于需要定义算法骨架但允许某些步骤由子类自定义的情况,例如,创建框架、工作流程或其他多步骤的操作。这有助于提高代码的可复用性和可维护性。
14.访问者模式(Visitor)
访问者模式(Visitor Pattern)是一种行为型设计模式,它用于分离数据结构和数据操作,并允许在不修改数据结构的情况下添加新的操作。访问者模式的核心思想是将数据结构和操作分离,使得数据结构可以在不同的操作下表现不同的行为。
访问者模式包含以下几个主要角色:
- 访问者(Visitor):访问者是一个抽象类或接口,它定义了一组访问操作,每个操作对应一个具体的元素类型。
- 具体访问者(Concrete Visitor):具体访问者是访问者接口的具体实现,每个具体访问者实现了一组具体的访问操作。
- 元素(Element) :元素是一个抽象类或接口,它定义了一个
accept
方法,该方法接受一个访问者对象作为参数,允许访问者访问该元素。 - 具体元素(Concrete Element) :具体元素是元素接口的具体实现,每个具体元素实现了
accept
方法,用于调用访问者的相应操作。 - 对象结构(Object Structure):对象结构是一个包含多个元素的集合,它通常提供一个接受访问者的方法,用于遍历元素并调用访问者的操作。
访问者模式的主要优点包括:
- 分离了数据结构和数据操作,使得可以添加新的操作而无需修改现有数据结构。
- 支持对数据结构进行不同的操作,从而提供更多的灵活性和扩展性。
- 使得数据结构可以遵循开闭原则(Open/Closed Principle),即对扩展开放,对修改关闭。
以下是一个简单的访问者模式的 C++ 示例:
cpp
#include <iostream>
#include <vector>
// 前向声明,让元素类知道访问者类
class Visitor;
// 元素接口
class Element {
public:
virtual void accept(Visitor& visitor) = 0;
};
// 具体元素 A
class ConcreteElementA : public Element {
public:
void accept(Visitor& visitor) override {
visitor.visitElementA(*this);
}
void operationA() {
std::cout << "Operation A on ConcreteElementA" << std::endl;
}
};
// 具体元素 B
class ConcreteElementB : public Element {
public:
void accept(Visitor& visitor) override {
visitor.visitElementB(*this);
}
void operationB() {
std::cout << "Operation B on ConcreteElementB" << std::endl;
}
};
// 访问者接口
class Visitor {
public:
virtual void visitElementA(ConcreteElementA& element) = 0;
virtual void visitElementB(ConcreteElementB& element) = 0;
};
// 具体访问者
class ConcreteVisitor : public Visitor {
public:
void visitElementA(ConcreteElementA& element) override {
element.operationA();
}
void visitElementB(ConcreteElementB& element) override {
element.operationB();
}
};
int main() {
ConcreteElementA elementA;
ConcreteElementB elementB;
ConcreteVisitor visitor;
elementA.accept(visitor);
elementB.accept(visitor);
return 0;
}
在这个示例中,我们有两种具体元素 ConcreteElementA
和 ConcreteElementB
,它们都实现了元素接口,并提供了 accept
方法,以允许访问者访问这些元素。
具体访问者 ConcreteVisitor
实现了访问者接口中定义的访问操作,其中包括操作 A 和操作 B。
通过访问者模式,我们可以在不修改元素类的情况下,为元素类添加新的操作(在这个示例中是操作 A 和操作 B)。这种分离数据结构和操作的设计模式使得代码更加灵活和可维护。
15.组合模式(Composite)
组合模式(Composite Pattern)是一种结构型设计模式,用于将对象组合成树状结构以表示"部分-整体"的层次结构。组合模式允许客户端以一致的方式处理单个对象和对象组合。
组合模式包含以下几个主要角色:
- 组件(Component):组件是一个抽象类或接口,它声明了管理子组件的方法,以及其他操作的接口。
- 叶子(Leaf):叶子是组件的具体实现,它表示树结构中的叶子节点,不包含子组件。
- 容器(Composite):容器是组件的具体实现,它表示树结构中的分支节点,可以包含子组件。容器类通常会实现管理子组件的方法。
组合模式的主要优点包括:
- 客户端可以以一致的方式处理单个对象和对象组合,无需知道具体组件的类型。
- 可以递归地构建复杂的对象结构,使代码具有更高的可扩展性。
- 通过组合模式,可以更容易地添加新的组件类型。
以下是一个简单的组合模式的 C++ 示例:
cpp
#include <iostream>
#include <vector>
// 抽象组件
class Component {
public:
virtual void operation() = 0;
};
// 叶子组件
class Leaf : public Component {
public:
void operation() override {
std::cout << "Leaf operation" << std::endl;
}
};
// 容器组件
class Composite : public Component {
public:
void operation() override {
std::cout << "Composite operation" << std::endl;
// 调用子组件的操作
for (Component* child : children_) {
child->operation();
}
}
void add(Component* component) {
children_.push_back(component);
}
private:
std::vector<Component*> children_;
};
int main() {
Leaf leaf1, leaf2;
Composite composite;
composite.add(&leaf1);
composite.add(&leaf2);
composite.operation();
return 0;
}
在这个示例中,我们有一个抽象组件 Component
,包括一个操作方法 operation
。Leaf
类是叶子组件,它是组件的具体实现,而 Composite
类是容器组件,它可以包含多个子组件。
在 main
函数中,我们创建了两个叶子组件和一个容器组件,并将叶子组件添加到容器组件中。当调用容器组件的 operation
方法时,它会递归调用其子组件的 operation
方法,从而实现了整体-部分的层次结构。
组合模式常用于处理树状结构,例如文件系统、图形界面控件、组织架构等情况,其中可以递归地组合和管理各种对象。
16.迭代器模式
迭代器模式(Iterator Pattern)是一种行为型设计模式,用于提供一种访问聚合对象中各个元素的方法,而无需暴露聚合对象的内部表示。迭代器模式将遍历聚合对象的操作封装在一个迭代器对象中,使客户端能够以一致的方式遍历不同类型的聚合对象。
迭代器模式包含以下几个主要角色:
- 迭代器(Iterator):迭代器是一个抽象接口,它定义了用于遍历聚合对象的方法,包括移动到下一个元素、检查是否还有元素等操作。
- 具体迭代器(Concrete Iterator):具体迭代器是迭代器接口的具体实现,它实现了在特定聚合对象上的遍历方法。
- 聚合(Aggregate):聚合是一个抽象接口,它定义了用于创建迭代器的方法。
- 具体聚合(Concrete Aggregate):具体聚合是聚合接口的具体实现,它包含了一组元素,可以生成相应的具体迭代器。
迭代器模式的主要优点包括:
- 客户端可以通过迭代器以一致的方式遍历不同类型的聚合对象,无需关心具体的数据结构。
- 迭代器模式将遍历操作封装在独立的迭代器对象中,使聚合对象的结构保持私有,提高了封装性。
- 支持多种迭代方式,例如正向遍历、反向遍历、跳跃式遍历等。
以下是一个简单的迭代器模式的 C++ 示例:
cpp
#include <iostream>
#include <vector>
// 抽象迭代器
class Iterator {
public:
virtual int next() = 0;
virtual bool hasNext() = 0;
};
// 具体迭代器
class ConcreteIterator : public Iterator {
public:
ConcreteIterator(const std::vector<int>& collection) : collection_(collection), index_(0) {}
int next() override {
return collection_[index_++];
}
bool hasNext() override {
return index_ < collection_.size();
}
private:
std::vector<int> collection_;
int index_;
};
// 抽象聚合
class Aggregate {
public:
virtual Iterator* createIterator() = 0;
};
// 具体聚合
class ConcreteAggregate : public Aggregate {
public:
ConcreteAggregate(const std::vector<int>& collection) : collection_(collection) {}
Iterator* createIterator() override {
return new ConcreteIterator(collection_);
}
private:
std::vector<int> collection_;
};
int main() {
std::vector<int> data = {1, 2, 3, 4, 5};
ConcreteAggregate aggregate(data);
Iterator* iterator = aggregate.createIterator();
while (iterator->hasNext()) {
std::cout << iterator->next() << " ";
}
delete iterator;
return 0;
}
在这个示例中,我们有一个抽象迭代器 Iterator
,具体迭代器 ConcreteIterator
,抽象聚合 Aggregate
,以及具体聚合 ConcreteAggregate
。
具体聚合 ConcreteAggregate
包含了一组整数元素,并提供了创建迭代器的方法。具体迭代器 ConcreteIterator
实现了在集合上的遍历操作。
在 main
函数中,我们创建了一个包含整数的聚合对象,然后创建了一个迭代器对象,通过迭代器以一致的方式遍历聚合中的元素。这种设计模式使得客户端可以在不关心聚合内部结构的情况下进行遍历操作。
17.中介者模式(Mediator)
中介者模式(Mediator Pattern)是一种行为型设计模式,它用于减少对象之间的直接通信,将对象间的交互通过一个中介者对象进行协调和控制。中介者模式有助于降低系统中对象之间的耦合度,使系统更易维护和扩展。
中介者模式包含以下几个主要角色:
- 中介者(Mediator):中介者是一个接口或抽象类,它定义了对象之间交互的方法,包括注册、通知、协调等。
- 具体中介者(Concrete Mediator):具体中介者是中介者接口的具体实现,它协调各个相关对象之间的交互,并维护对象之间的引用。
- 同事类(Colleague):同事类是相互交互的对象,它们通过中介者来进行通信,而不直接依赖其他同事类。
中介者模式的主要优点包括:
- 降低了对象之间的直接耦合,使系统更加灵活和可维护。
- 可以集中控制对象之间的交互,使系统的交互逻辑更清晰。
- 支持新增和删除同事类,对系统扩展更加友好。
以下是一个简单的中介者模式的 C++ 示例:
cpp
#include <iostream>
#include <string>
// 抽象中介者
class Mediator {
public:
virtual void sendMessage(const std::string& message, class Colleague* colleague) = 0;
};
// 具体中介者
class ConcreteMediator : public Mediator {
public:
void sendMessage(const std::string& message, class Colleague* colleague) override {
std::cout << "Message from " << colleague->getName() << ": " << message << std::endl;
}
};
// 同事类
class Colleague {
public:
Colleague(const std::string& name, Mediator* mediator) : name_(name), mediator_(mediator) {}
void sendMessage(const std::string& message) {
mediator_->sendMessage(message, this);
}
const std::string& getName() {
return name_;
}
private:
std::string name_;
Mediator* mediator_;
};
int main() {
ConcreteMediator mediator;
Colleague colleague1("Colleague 1", &mediator);
Colleague colleague2("Colleague 2", &mediator);
colleague1.sendMessage("Hello from Colleague 1");
colleague2.sendMessage("Hi from Colleague 2");
return 0;
}
在这个示例中,我们有一个抽象中介者 Mediator
,具体中介者 ConcreteMediator
,以及两个同事类 Colleague
。同事类通过中介者来发送消息,而不直接与其他同事类进行通信。
中介者模式在协调对象之间的交互时非常有用,特别是在大型系统中,当对象之间的交互关系复杂时,可以通过引入中介者来简化和集中控制交互逻辑。这有助于减少系统的复杂性和提高可维护性。
18.备忘录模式(Memento)
备忘录模式(Memento Pattern)是一种行为型设计模式,它用于捕获一个对象的内部状态,并将其保存在一个外部对象中,从而可以在以后将对象恢复到先前的状态。备忘录模式的关键思想是在不破坏封装性的前提下,将对象的状态保存和恢复。
备忘录模式包含以下几个主要角色:
- 发起人(Originator):发起人是需要保存状态的对象。它有一个创建备忘录和恢复备忘录的方法。发起人的状态可能会变化,可以使用备忘录来保存不同时间点的状态。
- 备忘录(Memento):备忘录是保存发起人状态的对象。它包含了发起人在某一时刻的状态信息。
- 管理者(Caretaker):管理者是用于保存和管理备忘录的对象。它可以保存多个备忘录,以便在需要时恢复发起人的状态。
备忘录模式的主要优点包括:
- 允许在不破坏封装性的情况下保存对象的状态,从而可以实现状态的撤销和恢复操作。
- 提供了一种简单的方式来保存和管理对象的历史状态,支持多次撤销操作。
- 可以降低发起人对象的复杂性,因为状态保存和恢复的逻辑由备忘录和管理者处理。
以下是一个简单的备忘录模式的 C++ 示例:
cpp
#include <iostream>
#include <string>
// 备忘录类
class Memento {
public:
Memento(const std::string& state) : state_(state) {}
const std::string& getState() {
return state_;
}
private:
std::string state_;
};
// 发起人类
class Originator {
public:
void setState(const std::string& state) {
state_ = state;
}
const std::string& getState() {
return state_;
}
Memento createMemento() {
return Memento(state_);
}
void restoreMemento(const Memento& memento) {
state_ = memento.getState();
}
private:
std::string state_;
};
// 管理者类
class Caretaker {
public:
void saveMemento(const Memento& memento) {
mementos_.push_back(memento);
}
Memento getMemento(int index) {
if (index >= 0 && index < mementos_.size()) {
return mementos_[index];
}
// 返回一个空的备忘录以示错误
return Memento("");
}
private:
std::vector<Memento> mementos_;
};
int main() {
Originator originator;
Caretaker caretaker;
// 设置初始状态并保存备忘录
originator.setState("State 1");
caretaker.saveMemento(originator.createMemento());
// 修改状态并保存备忘录
originator.setState("State 2");
caretaker.saveMemento(originator.createMemento());
// 恢复到第一个备忘录状态
originator.restoreMemento(caretaker.getMemento(0));
std::cout << "Current state: " << originator.getState() << std::endl;
return 0;
}
在这个示例中,Originator
类表示发起人,它有一个状态需要保存。Memento
类表示备忘录,它可以保存发起人的状态。Caretaker
类表示管理者,它可以保存和管理备忘录。
在 main
函数中,我们设置了初始状态,并保存了备忘录。然后,修改状态并再次保存备忘录。最后,我们恢复到第一个备忘录状态,从而实现了状态的撤销和恢复操作。备忘录模式非常有用,特别是在需要实现撤销和恢复功能的应用中。
19.桥接模式
桥接模式(Bridge Pattern)是一种结构型设计模式,它用于将抽象部分与实现部分分离,以便它们可以独立地变化。桥接模式的目的是将继承关系转化为组合关系,从而减少类之间的耦合度,提高系统的可扩展性。
桥接模式包含以下几个主要角色:
- 抽象部分(Abstraction):抽象部分定义了对实现部分的接口,它维护一个对实现部分的引用,并可以通过委托给实现部分来完成具体的操作。
- 扩展抽象部分(Refined Abstraction):扩展抽象部分是对抽象部分的扩展,通常会增加一些额外的操作。
- 实现部分(Implementor):实现部分定义了具体操作的接口,它可以是一个抽象类或接口,也可以是具体类。
- 具体实现部分(Concrete Implementor):具体实现部分是实现部分的具体实现,它实现了实现部分定义的接口。
桥接模式的主要优点包括:
- 分离抽象部分和实现部分,使它们可以独立变化,增加了系统的灵活性。
- 对于不同的抽象部分,可以选择不同的实现部分,从而实现了多样化的组合。
- 提高了系统的可扩展性,新的抽象部分和实现部分可以方便地添加。
以下是一个简单的桥接模式的 C++ 示例:
cpp
#include <iostream>
// 实现部分接口
class Implementor {
public:
virtual void operationImpl() = 0;
};
// 具体实现部分 A
class ConcreteImplementorA : public Implementor {
public:
void operationImpl() override {
std::cout << "Concrete Implementor A operation" << std::endl;
}
};
// 具体实现部分 B
class ConcreteImplementorB : public Implementor {
public:
void operationImpl() override {
std::cout << "Concrete Implementor B operation" << std::endl;
}
};
// 抽象部分
class Abstraction {
public:
Abstraction(Implementor* implementor) : implementor_(implementor) {}
virtual void operation() {
implementor_->operationImpl();
}
private:
Implementor* implementor_;
};
// 扩展抽象部分
class RefinedAbstraction : public Abstraction {
public:
RefinedAbstraction(Implementor* implementor) : Abstraction(implementor) {}
void additionalOperation() {
std::cout << "Additional operation" << std::endl;
}
};
int main() {
Implementor* implA = new ConcreteImplementorA();
Implementor* implB = new ConcreteImplementorB();
Abstraction* abstraction1 = new Abstraction(implA);
abstraction1->operation();
Abstraction* abstraction2 = new RefinedAbstraction(implB);
abstraction2->operation();
static_cast<RefinedAbstraction*>(abstraction2)->additionalOperation();
delete implA;
delete implB;
delete abstraction1;
delete abstraction2;
return 0;
}
在这个示例中,我们有两个实现部分:ConcreteImplementorA
和 ConcreteImplementorB
,它们实现了 Implementor
接口。然后,我们有抽象部分 Abstraction
和扩展抽象部分 RefinedAbstraction
,它们使用实现部分来完成操作。
在 main
函数中,我们创建了两个不同的实现部分,然后分别将它们与抽象部分和扩展抽象部分组合。通过这种方式,我们可以轻松地改变抽象部分和实现部分的组合,实现不同的操作。这是桥接模式的典型应用。
20.解释器模式(Interpreter)
解释器模式(Interpreter Pattern)是一种行为型设计模式,它用于定义一种语言的文法规则,并提供一个解释器来解释语言中的表达式。该模式将一个句子(语法)分解成一系列的解释动作。解释器模式常用于编译器、解析器和领域特定语言的实现中。
解释器模式包含以下几个主要角色:
- 抽象表达式(Abstract Expression) :抽象表达式定义了解释器的接口,包含一个
interpret
方法用于解释表达式。 - 终结符表达式(Terminal Expression) :终结符表达式是继承自抽象表达式的类,它实现了
interpret
方法用于解释终结符表达式。 - 非终结符表达式(Non-terminal Expression) :非终结符表达式也是继承自抽象表达式的类,它通常包含多个子表达式,并实现了
interpret
方法用于解释非终结符表达式。 - 上下文(Context):上下文包含要解释的文法规则的信息,通常包含解释器所需的数据。
- 客户端(Client):客户端创建并配置解释器,然后使用解释器来解释表达式。
解释器模式的主要优点是可以扩展语言的语法,以及在一些特定领域中解决问题。然而,它也有一些缺点,例如对于复杂的文法规则,解释器模式可能会变得复杂,难以维护。
以下是一个简单的解释器模式的 C++ 示例:
cpp
#include <iostream>
#include <unordered_map>
// 抽象表达式
class Expression {
public:
virtual int interpret(std::unordered_map<char, int>& context) = 0;
};
// 终结符表达式
class TerminalExpression : public Expression {
public:
TerminalExpression(char variable) : variable_(variable) {}
int interpret(std::unordered_map<char, int>& context) override {
return context[variable_];
}
private:
char variable_;
};
// 非终结符表达式
class NonterminalExpression : public Expression {
public:
NonterminalExpression(Expression* left, Expression* right) : left_(left), right_(right) {}
int interpret(std::unordered_map<char, int>& context) override {
return left_->interpret(context) + right_->interpret(context);
}
private:
Expression* left_;
Expression* right_;
};
int main() {
std::unordered_map<char, int> context;
context['a'] = 5;
context['b'] = 10;
Expression* expression = new NonterminalExpression(
new TerminalExpression('a'),
new TerminalExpression('b')
);
int result = expression->interpret(context);
std::cout << "Result: " << result << std::endl;
delete expression;
return 0;
}
在这个示例中,我们创建了一个简单的表达式语言,包括终结符表达式和非终结符表达式。通过解释器模式,我们可以解释这些表达式并计算结果。这个示例是解释器模式的一个简单演示,实际应用中可能会涉及更复杂的语法和解释器。
总结
设计模式是一种通用的解决问题的模板或蓝图,它们用于解决特定类型的问题,并为软件设计提供了可重用的解决方案。在计算机科学中,有23种广泛接受的经典设计模式,它们通常被分为以下几个类别:
-
创建型模式(Creational Patterns):这些模式关注对象的创建机制,以便以适当的方式创建对象,隐藏创建的细节。创建型模式包括:
- 单例模式(Singleton Pattern)
- 工厂模式(Factory Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
- 建造者模式(Builder Pattern)
- 原型模式(Prototype Pattern)
-
结构型模式(Structural Patterns):这些模式处理对象之间的组合,以便形成更大的结构。结构型模式包括:
- 适配器模式(Adapter Pattern)
- 桥接模式(Bridge Pattern)
- 组合模式(Composite Pattern)
- 装饰器模式(Decorator Pattern)
- 外观模式(Facade Pattern)
- 享元模式(Flyweight Pattern)
- 代理模式(Proxy Pattern)
-
行为型模式(Behavioral Patterns):这些模式关注对象之间的通信、职责分配和协作。行为型模式包括:
- 责任链模式(Chain of Responsibility Pattern)
- 命令模式(Command Pattern)
- 解释器模式(Interpreter Pattern)
- 迭代器模式(Iterator Pattern)
- 中介者模式(Mediator Pattern)
- 备忘录模式(Memento Pattern)
- 观察者模式(Observer Pattern)
- 状态模式(State Pattern)
- 策略模式(Strategy Pattern)
- 模板方法模式(Template Method Pattern)
- 访问者模式(Visitor Pattern)
这些经典的设计模式提供了在特定情况下解决问题的有效方法,它们有助于提高软件的可维护性、可扩展性和可重用性。根据应用场景和需求,开发人员可以选择适当的设计模式来构建更健壮、可维护和可扩展的软件系统。