C++中常用的设计模式有很多,设计模式是解决常见问题的经过验证的最佳实践。以下是一些常用的设计模式:
这些设计模式都有特定的应用场景,可以根据问题的性质选择合适的设计模式来解决。设计模式有助于提高代码的可维护性、可扩展性和复用性。
提供所有设计模式的 C++ 示例代码是一个庞大的任务,但我可以为您提供一个示例,演示如何使用 C++ 实现一个常见的设计模式——单例模式(Singleton)。
单例模式(Singleton) 确保一个类只有一个实例,并提供全局访问点。以下是一个基本的单例模式示例:
#include
class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance; // 静态局部变量确保只初始化一次
return instance;
}
void doSomething() {
std::cout << "Singleton is doing something." << std::endl;
}
private:
Singleton() {} // 构造函数私有,只能通过 getInstance() 获取实例
};
int main() {
// 获取 Singleton 实例
Singleton& singleton = Singleton::getInstance();
singleton.doSomething();
return 0;
}
在这个示例中,Singleton
类的构造函数是私有的,这意味着外部无法直接创建 Singleton
对象。通过 getInstance()
静态成员函数,我们可以获取到单一的 Singleton
实例。这确保了只有一个实例存在。
单例模式常用于需要共享资源或控制访问某些全局状态的情况。在实际项目中,设计模式的选择会根据具体需求和架构决策,不同的模式可能会以不同的方式被实现和使用。
工厂模式(Factory Pattern)是一种创建型设计模式,用于创建对象而无需指定对象的具体类。工厂模式通过定义一个共同的接口,由不同的工厂子类来实现,并根据不同的情况返回不同的具体对象。
以下是一个简单的工厂模式的 C++ 示例:
#include
// 抽象产品类
class Product {
public:
virtual void use() = 0;
};
// 具体产品类 A
class ConcreteProductA : public Product {
public:
void use() override {
std::cout << "Product A in use." << std::endl;
}
};
// 具体产品类 B
class ConcreteProductB : public Product {
public:
void use() override {
std::cout << "Product B in use." << std::endl;
}
};
// 抽象工厂类
class Factory {
public:
virtual Product* createProduct() = 0;
};
// 具体工厂类 A,用于创建 ProductA
class ConcreteFactoryA : public Factory {
public:
Product* createProduct() override {
return new ConcreteProductA();
}
};
// 具体工厂类 B,用于创建 ProductB
class ConcreteFactoryB : public Factory {
public:
Product* createProduct() override {
return new ConcreteProductB();
}
};
int main() {
// 使用具体工厂类 A 创建产品 A
Factory* factoryA = new ConcreteFactoryA();
Product* productA = factoryA->createProduct();
productA->use();
// 使用具体工厂类 B 创建产品 B
Factory* factoryB = new ConcreteFactoryB();
Product* productB = factoryB->createProduct();
productB->use();
delete factoryA;
delete factoryB;
delete productA;
delete productB;
return 0;
}
在这个示例中,我们定义了抽象产品类 Product
,有两个具体的产品类 ConcreteProductA
和 ConcreteProductB
,它们都继承自 Product
。然后,我们定义了抽象工厂类 Factory
,有两个具体工厂类 ConcreteFactoryA
和 ConcreteFactoryB
,它们分别负责创建不同的产品。
通过使用工厂模式,我们可以根据具体的需求选择不同的工厂类来创建产品,而无需关心产品的具体类是什么。这提供了灵活性,允许我们轻松扩展和替换具体产品和工厂类。
这是一个简单的示例,实际中工厂模式可用于更复杂的对象创建需求。工厂模式常用于创建对象的场景,特别是在代码中需要降低耦合性时非常有用。
抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一个接口,用于创建一系列相关或依赖的对象,而不需要指定它们的具体类。抽象工厂模式的核心思想是为每个产品族(相关的一组产品)定义一个抽象工厂,然后在每个具体工厂中实现该抽象工厂。
以下是一个简单的抽象工厂模式的 C++ 示例:
#include
// 抽象产品 A
class AbstractProductA {
public:
virtual void useA() = 0;
};
// 具体产品 A1
class ConcreteProductA1 : public AbstractProductA {
public:
void useA() override {
std::cout << "Product A1 in use." << std::endl;
}
};
// 具体产品 A2
class ConcreteProductA2 : public AbstractProductA {
public:
void useA() override {
std::cout << "Product A2 in use." << std::endl;
}
};
// 抽象产品 B
class AbstractProductB {
public:
virtual void useB() = 0;
};
// 具体产品 B1
class ConcreteProductB1 : public AbstractProductB {
public:
void useB() override {
std::cout << "Product B1 in use." << std::endl;
}
};
// 具体产品 B2
class ConcreteProductB2 : public AbstractProductB {
public:
void useB() override {
std::cout << "Product B2 in use." << 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() {
// 使用具体工厂 1 创建产品 A 和 B
AbstractFactory* factory1 = new ConcreteFactory1();
AbstractProductA* productA1 = factory1->createProductA();
AbstractProductB* productB1 = factory1->createProductB();
productA1->useA();
productB1->useB();
// 使用具体工厂 2 创建产品 A 和 B
AbstractFactory* factory2 = new ConcreteFactory2();
AbstractProductA* productA2 = factory2->createProductA();
AbstractProductB* productB2 = factory2->createProductB();
productA2->useA();
productB2->useB();
delete factory1;
delete productA1;
delete productB1;
delete factory2;
delete productA2;
delete productB2;
return 0;
}
在这个示例中,我们定义了两个抽象产品类 AbstractProductA
和 AbstractProductB
,以及它们的具体实现类。然后,我们定义了抽象工厂类 AbstractFactory
,它包括两个工厂方法,分别用于创建产品 A 和产品 B。具体工厂类 ConcreteFactory1
和 ConcreteFactory2
分别实现了 AbstractFactory
,用于创建不同的产品族。
抽象工厂模式允许我们在不知道具体产品类的情况下创建一组相关产品,这对于需要保持产品族之间的一致性非常有用。此模式还支持易于替换整个产品族,以满足不同的需求。
建造者模式(Builder Pattern)是一种创建型设计模式,用于构建一个复杂对象,将构造过程和表示分离。通常情况下,该模式包括一个 Director(指挥者)类、一个抽象 Builder(建造者)接口和具体的 Builder 实现类。
以下是一个简单的建造者模式的 C++ 示例:
#include
#include
// 产品类,即要构建的复杂对象
class Product {
public:
void setPartA(const std::string& partA) {
partA_ = partA;
}
void setPartB(const std::string& partB) {
partB_ = partB;
}
void setPartC(const std::string& partC) {
partC_ = partC;
}
void show() {
std::cout << "Product parts: " << partA_ << ", " << partB_ << ", " << partC_ << std::endl;
}
private:
std::string partA_;
std::string partB_;
std::string partC_;
};
// 抽象 Builder 接口
class Builder {
public:
virtual void buildPartA() = 0;
virtual void buildPartB() = 0;
virtual void buildPartC() = 0;
virtual Product getResult() = 0;
};
// 具体 Builder 实现
class ConcreteBuilder : public Builder {
public:
ConcreteBuilder() {
product_ = new Product();
}
void buildPartA() override {
product_->setPartA("Part A");
}
void buildPartB() override {
product_->setPartB("Part B");
}
void buildPartC() override {
product_->setPartC("Part C");
}
Product getResult() override {
return *product_;
}
private:
Product* product_;
};
// 指挥者类,负责构建产品
class Director {
public:
Director(Builder* builder) : builder_(builder) {}
Product construct() {
builder_->buildPartA();
builder_->buildPartB();
builder_->buildPartC();
return builder_->getResult();
}
private:
Builder* builder_;
};
int main() {
ConcreteBuilder builder;
Director director(&builder);
Product product = director.construct();
product.show();
return 0;
}
在这个示例中,我们有一个产品类 Product
,包括三个部分。我们定义了抽象 Builder 接口,包括构建每个部分的方法和获取最终产品的方法。具体 Builder 类 ConcreteBuilder
实现了 Builder 接口,构建了 Product
的各个部分。指挥者类 Director
负责指导 Builder 构建产品。
使用建造者模式,我们可以按照不同的需求构建不同的产品,而不必关心构建的细节。这种模式尤其适用于构建复杂对象,帮助将构建过程和表示分离,提高了可维护性和可扩展性。
原型模式(Prototype Pattern)是一种创建型设计模式,其主要思想是通过复制现有对象(原型)来创建新对象,而不需要从头开始构建。这种模式通常用于创建成本高昂或复杂的对象,同时可以保持对象的不变性。原型模式基于对象的克隆,可以分为浅拷贝和深拷贝两种。
以下是一个简单的原型模式的 C++ 示例:
#include
#include
// 原型类
class Prototype {
public:
virtual Prototype* clone() = 0;
virtual void print() = 0;
};
// 具体原型类 A
class ConcretePrototypeA : public Prototype {
public:
Prototype* clone() override {
return new ConcretePrototypeA(*this); // 深拷贝
}
void print() override {
std::cout << "ConcretePrototypeA" << std::endl;
}
};
// 具体原型类 B
class ConcretePrototypeB : public Prototype {
public:
Prototype* clone() override {
return new ConcretePrototypeB(*this); // 深拷贝
}
void print() override {
std::cout << "ConcretePrototypeB" << std::endl;
}
};
int main() {
Prototype* originalA = new ConcretePrototypeA();
Prototype* originalB = new ConcretePrototypeB();
// 克隆原型对象
Prototype* cloneA = originalA->clone();
Prototype* cloneB = originalB->clone();
originalA->print();
cloneA->print();
originalB->print();
cloneB->print();
delete originalA;
delete cloneA;
delete originalB;
delete cloneB;
return 0;
}
在这个示例中,我们定义了一个抽象原型类 Prototype
,包括克隆方法 clone
和打印方法 print
。然后,我们创建了两个具体的原型类 ConcretePrototypeA
和 ConcretePrototypeB
,它们实现了克隆方法,并在打印方法中展示自己的类型。
在 main
函数中,我们首先创建原型对象 originalA
和 originalB
,然后通过调用它们的 clone
方法,创建了相应的克隆对象 cloneA
和 cloneB
。这些克隆对象与原型对象具有相同的状态,但是是独立的对象。
原型模式允许我们根据需要克隆对象,而不必重新创建。这对于创建成本高昂或复杂的对象,以及需要保持对象不变性的情况非常有用。需要注意的是,深拷贝和浅拷贝的选择取决于对象内部的状态和结构。在实际应用中,可能需要自定义克隆方法以适应特定需求。
适配器模式(Adapter Pattern)是一种结构型设计模式,它允许一个类的接口与另一个类的接口兼容。适配器模式主要用于解决两个已有接口之间的不匹配问题,使它们可以一起工作,而不需要修改它们的源代码。
适配器模式有两种主要类型:类适配器和对象适配器。
类适配器 使用多重继承,它继承了被适配类并实现了目标接口。
对象适配器 维护一个被适配类的实例,并实现了目标接口,然后委托被适配类的实例来执行相应的操作。
以下是一个简单的对象适配器模式的 C++ 示例:
#include
// 目标接口
class Target {
public:
virtual void request() = 0;
};
// 被适配类
class Adaptee {
public:
void specificRequest() {
std::cout << "Adaptee's specific request." << std::endl;
}
};
// 对象适配器
class Adapter : public Target {
public:
Adapter(Adaptee* adaptee) : adaptee_(adaptee) {}
void request() override {
adaptee_->specificRequest();
}
private:
Adaptee* adaptee_;
};
int main() {
Adaptee adaptee;
Target* adapter = new Adapter(&adaptee);
adapter->request();
delete adapter;
return 0;
}
在这个示例中,我们有一个目标接口 Target
,包括 request
方法。我们还有一个被适配类 Adaptee
,它包括 specificRequest
方法,但它的接口与 Target
不兼容。
然后,我们创建了一个对象适配器 Adapter
,它实现了 Target
接口,并维护了一个 Adaptee
的实例。在 Adapter
的 request
方法中,我们将调用委托给 Adaptee
的 specificRequest
方法,从而使 Adaptee
可以与 Target
接口兼容。
适配器模式在现实中的应用非常广泛,特别是在将旧系统与新系统集成或者使用第三方库时,它可以起到很好的桥梁作用,以确保不同接口之间的兼容性。
类适配器
类适配器模式使用多重继承来实现适配,它继承了被适配类并实现了目标接口。以下是一个简单的类适配器模式的 C++ 示例:
#include
// 目标接口
class Target {
public:
virtual void request() = 0;
};
// 被适配类
class Adaptee {
public:
void specificRequest() {
std::cout << "Adaptee's specific request." << std::endl;
}
};
// 类适配器,继承自 Adaptee 和实现 Target 接口
class Adapter : public Adaptee, public Target {
public:
void request() override {
specificRequest(); // 调用 Adaptee 的方法
}
};
int main() {
Target* adapter = new Adapter();
adapter->request();
delete adapter;
return 0;
}
在这个示例中,我们有一个目标接口 Target
,包括 request
方法。我们还有一个被适配类 Adaptee
,它包括 specificRequest
方法,但它的接口与 Target
不兼容。
然后,我们创建了一个类适配器 Adapter
,它继承自 Adaptee
并实现了 Target
接口。在 Adapter
的 request
方法中,我们可以直接调用 specificRequest
方法,因为 Adapter
继承了 Adaptee
。
类适配器模式使用多重继承,这使得它可以同时继承多个类,但也可能引入一些复杂性。适配器模式可用于解决现有系统的接口不兼容问题,同时不需要修改被适配类的源代码。
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你通过将对象包装在装饰器类的实例中来动态地扩展其行为,而不需要修改其源代码。装饰器模式通常用于以下情况:
以下是一个简单的装饰器模式的 C++ 示例:
#include
// 抽象组件接口
class Component {
public:
virtual void operation() = 0;
};
// 具体组件
class ConcreteComponent : public Component {
public:
void operation() override {
std::cout << "ConcreteComponent operation." << std::endl;
}
};
// 抽象装饰器
class Decorator : public Component {
public:
Decorator(Component* component) : component_(component) {}
void operation() override {
component_->operation();
}
private:
Component* component_;
};
// 具体装饰器 A
class ConcreteDecoratorA : public Decorator {
public:
ConcreteDecoratorA(Component* component) : Decorator(component) {}
void operation() override {
Decorator::operation();
std::cout << "ConcreteDecoratorA operation." << std::endl;
}
};
// 具体装饰器 B
class ConcreteDecoratorB : public Decorator {
public:
ConcreteDecoratorB(Component* component) : Decorator(component) {}
void operation() override {
Decorator::operation();
std::cout << "ConcreteDecoratorB operation." << std::endl;
}
};
int main() {
Component* component = new ConcreteComponent();
Component* decoratorA = new ConcreteDecoratorA(component);
Component* decoratorB = new ConcreteDecoratorB(decoratorA);
component->operation(); // 基本组件操作
decoratorA->operation(); // 增加了装饰器 A 的操作
decoratorB->operation(); // 增加了装饰器 A 和装饰器 B 的操作
delete component;
delete decoratorA;
delete decoratorB;
return 0;
}
在这个示例中,我们有一个抽象组件接口 Component
,包括 operation
方法。具体组件 ConcreteComponent
实现了这个接口。
然后,我们定义了抽象装饰器 Decorator
,它也实现了 Component
接口,但在 operation
方法中调用了包装的组件的 operation
方法。具体装饰器类 ConcreteDecoratorA
和 ConcreteDecoratorB
扩展了 Decorator
类,分别增加了特定的操作。
在 main
函数中,我们创建了一个基本组件 component
,然后依次用装饰器 decoratorA
和 decoratorB
包装它。通过这样的嵌套,我们可以动态地添加不同的行为,而不需要修改组件的源代码。
装饰器模式允许我们以一种灵活的方式组合对象,以满足不同需求。这可以帮助我们遵循开放/封闭原则,同时保持代码的可维护性和可扩展性。
代理模式(Proxy Pattern)是一种结构型设计模式,它允许你提供一个代理类,控制对其他对象的访问。代理模式通常用于以下情况:
以下是一个简单的代理模式的 C++ 示例:
#include
// 抽象主题
class Subject {
public:
virtual void request() = 0;
};
// 具体主题
class RealSubject : public Subject {
public:
void request() override {
std::cout << "RealSubject handles the request." << std::endl;
}
};
// 代理
class Proxy : public Subject {
public:
Proxy(Subject* realSubject) : realSubject_(realSubject) {}
void request() override {
if (checkAccess()) {
realSubject_->request();
logAccess();
} else {
std::cout << "Access denied." << std::endl;
}
}
private:
bool checkAccess() {
// 检查访问权限的逻辑
return true;
}
void logAccess() {
// 记录访问日志的逻辑
std::cout << "Access logged." << std::endl;
}
Subject* realSubject_;
};
int main() {
RealSubject realSubject;
Proxy proxy(&realSubject);
proxy.request();
return 0;
}
在这个示例中,我们有一个抽象主题 Subject
,包括 request
方法。具体主题 RealSubject
实现了这个接口,用于处理请求。
然后,我们创建了代理 Proxy
,它也实现了 Subject
接口。在 Proxy
的 request
方法中,我们可以添加额外的逻辑,例如检查访问权限和记录访问日志。如果权限检查通过,它将委托给实际主题 RealSubject
来处理请求。
代理模式使我们能够控制对对象的访问,同时可以添加各种额外的功能,例如权限控制、懒加载、缓存等。这对于保持代码的可维护性和可扩展性非常有帮助。
观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,使一个对象的状态发生变化时,其所有依赖者(观察者)都会收到通知并自动更新。观察者模式通常用于以下情况:
观察者模式包含以下几个关键角色:
以下是一个简单的观察者模式的 C++ 示例:
#include
#include
// 观察者接口
class Observer {
public:
virtual void update(const std::string& message) = 0;
};
// 主题接口
class Subject {
public:
virtual void addObserver(Observer* observer) = 0;
virtual void removeObserver(Observer* observer) = 0;
virtual void notifyObservers(const std::string& message) = 0;
};
// 具体观察者
class ConcreteObserver : public Observer {
public:
ConcreteObserver(const std::string& name) : name_(name) {}
void update(const std::string& message) override {
std::cout << name_ << " received message: " << message << std::endl;
}
private:
std::string name_;
};
// 具体主题
class ConcreteSubject : public Subject {
public:
void addObserver(Observer* observer) override {
observers_.push_back(observer);
}
void removeObserver(Observer* observer) override {
// 寻找并移除观察者
auto it = std::find(observers_.begin(), observers_.end(), observer);
if (it != observers_.end()) {
observers_.erase(it);
}
}
void notifyObservers(const std::string& message) override {
for (Observer* observer : observers_) {
observer->update(message);
}
}
private:
std::vector<Observer*> observers_;
};
int main() {
ConcreteSubject subject;
ConcreteObserver observer1("Observer 1");
ConcreteObserver observer2("Observer 2");
subject.addObserver(&observer1);
subject.addObserver(&observer2);
subject.notifyObservers("Hello, observers!");
subject.removeObserver(&observer1);
subject.notifyObservers("Observers after removal.");
return 0;
}
在这个示例中,我们定义了观察者接口 Observer
和主题接口 Subject
,分别包括添加、移除和通知观察者的方法。然后,我们创建了具体的观察者类 ConcreteObserver
和具体的主题类 ConcreteSubject
。
在 main
函数中,我们创建主题对象 subject
和两个观察者对象 observer1
和 observer2
。我们将观察者添加到主题中,然后主题通知观察者时,它们会接收到消息并执行相应的操作。
观察者模式使对象之间的关系松散,允许主题和观察者之间的独立变化,同时保持了对象之间的协作。这种模式常用于实现事件处理、发布-订阅系统以及任何需要实现对象之间松耦合通信的情况。
策略模式(Strategy Pattern)是一种行为型设计模式,它允许定义一系列算法,并将每个算法封装到独立的策略类中,使这些算法可以互相替换。策略模式的核心思想是将算法的选择与使用分离,从而实现更灵活的算法切换,同时不需要修改上下文类的代码。
策略模式包含以下几个主要角色:
使用策略模式的主要优点包括:
以下是一个简单的策略模式的 C++ 示例:
#include
// 策略接口
class Strategy {
public:
virtual void doOperation() = 0;
};
// 具体策略 A
class ConcreteStrategyA : public Strategy {
public:
void doOperation() override {
std::cout << "Using Strategy A" << std::endl;
}
};
// 具体策略 B
class ConcreteStrategyB : public Strategy {
public:
void doOperation() override {
std::cout << "Using Strategy B" << std::endl;
}
};
// 上下文
class Context {
public:
Context(Strategy* strategy) : strategy_(strategy) {}
void setStrategy(Strategy* strategy) {
strategy_ = strategy;
}
void executeStrategy() {
strategy_->doOperation();
}
private:
Strategy* strategy_;
};
int main() {
ConcreteStrategyA strategyA;
ConcreteStrategyB strategyB;
Context context(&strategyA);
context.executeStrategy();
context.setStrategy(&strategyB);
context.executeStrategy();
return 0;
}
在这个示例中,我们有一个策略接口 Strategy
,定义了算法族的接口。然后,我们创建了两个具体策略类 ConcreteStrategyA
和 ConcreteStrategyB
,分别实现了不同的算法。
上下文类 Context
包含一个策略对象的引用,它可以在运行时切换不同的策略。当调用 executeStrategy
方法时,上下文类会委托策略对象执行相应的算法。
策略模式的应用范围很广,可以用于任何需要动态地选择算法的场景,例如排序算法、计算费用、路由策略等。