前言:本文详细解释几种常用的C++设计模式,都是平时项目中用的比较多的。本文针对每种设计模式都给出了示例,让你跟着代码彻底搞懂设计模式。
Tips:如果是准备面试,
不需要知道所有的设计模式,要深入理解下面几种常用即可
,因为面试官会先问你了解哪些设计模式,然后从你了解的里面挑一个深问,而且很有可能还会让你手撕出来。而且,最好提前准备一下自己的项目中哪里用到了你说的设计模式,面试官也可能会问。
文章目录
C++常用设计模式
单例模式
单例模式确保一个类只有一个实例,并提供一个全局访问点来访问该实例。主要用于控制全局资源,如日志管理器、线程池、配置管理器等。
实现方式:
- 构造函数为私有,防止外部创建对象。
- 提供一个静态方法,负责创建或获取该类的唯一实例。
- 确保线程安全性。
class Singleton {
private:
Singleton() {}
public:
static Singleton& getInstance() {
static Singleton instance;
return instance;
}
// 禁止拷贝和赋值操作
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
C++11规定了局部静态变量在多线程条件下的初始化行为,要求编译器保证了局部静态变量的线程安全性。这样,只有当第一次访问getInstance()方法时才创建实例。C++11之后该实现是线程安全的,C++11之前仍需加锁。
工厂模式
用于创建对象(产品类)的接口,而不暴露对象创建的具体逻辑。适合于需要创建多个相似对象的场景,比如:图形界面组件、数据库连接。
简单工厂模式
建⽴⼀个⼯⼚类,对实现了同⼀接⼝的⼀些类(产品类)进⾏实例的创建。简单⼯⼚模式的实质是由⼀个⼯⼚类根据传⼊的参数,动态决定应该创建哪⼀个产品类(这些产品类继承⾃⼀个⽗类或接⼝)的实例。
// 产品类(抽象类,不能实例化)
class Product {
public:
virtual void show() = 0;
};
class ConcreteProductA : public Product {
public:
void show() override { std::cout << "Product A\n"; }
};
class ConcreteProductB : public Product {
public:
void show() override { std::cout << "Product B\n"; }
};
// ⼯⼚类
class Factory {
public:
Product* product(const string str){
if (str == "productA")
return new ConcreteProductA();
if (str == "productB")
return new ConcreteProductB();
return nullptr;
};
};
抽象工厂模式
为了进⼀步解耦,在简单⼯⼚的基础上发展出了抽象⼯⼚模式,即连⼯⼚都抽象出来,实现了进⼀步代码解耦。通过定义一个用于创建对象的接口,让工厂子类决定实例化哪个类。工厂模式的核心思想是将对象的创建和使用分离,以提高灵活性和扩展性。
实现方式:
- 定义一个工厂基类,声明一个创建产品的接口。
- 工厂子类实现这个接口,负责具体产品的创建。
class Product {
public:
virtual void show() = 0;
};
class ConcreteProductA : public Product {
public:
void show() override { std::cout << "Product A\n"; }
};
class ConcreteProductB : public Product {
public:
void show() override { std::cout << "Product B\n"; }
};
class Factory {
public:
virtual Product* createProduct() = 0;
};
class ConcreteFactoryA : public Factory {
public:
Product* createProduct() override {
return new ConcreteProductA();
}
};
class ConcreteFactoryB : public Factory {
public:
Product* createProduct() override {
return new ConcreteProductB();
}
};
观察者模式
定义了对象之间一对多的依赖关系,让多个观察对象同时监听⼀个被观察对象,被观察对象状态发⽣变化时,会通知所有的观察对象,使他们能够更新⾃⼰的状态。该模式常用于事件驱动系统、消息发布-订阅系统。
观察者模式中存在两种⻆⾊:
- 观察者:内部包含被观察者对象,当被观察者对象的状态发⽣变化时,更新自己的状态。(接收通知更新状态)
- 被观察者:内部包含了所有观察者对象,当状态发⽣变化时通知所有的观察者更新自己的状态。(发送通知)
实现方式:
- 定义一个被观察者(Subject)接口,允许添加、删除观察者。
- 定义观察者接口,声明更新方法。
- 被观察者在状态发生变化时,通知所有观察者调用更新方法。
// 观察者
class Observer {
public:
virtual void update(int value) = 0;
};
class ConcreteObserver : public Observer {
private:
int observerValue;
public:
// 被观察者对象的状态发⽣变化时,更新自己的状态
void update(int value) override {
observerValue = value;
std::cout << "Observer value updated to " << observerValue << "\n";
}
};
// 被观察者
class Subject {
private:
std::vector<Observer*> observers; // 存放所有观察者
int state;
public:
void attach(Observer* observer) {
observers.push_back(observer);
}
void setState(int value) {
state = value;
notify();
}
// 通知所有的观察者更新自己的状态
void notify() {
for (Observer* observer : observers) {
observer->update(state);
}
}
};
装饰器模式
装饰器模式允许向现有对象动态地添加行为,而不影响其他同类对象。该模式通常用于给对象增加功能,同时保持对象的结构灵活可扩展。
实现方式:
- 定义一个组件接口,声明可以被装饰的操作。
- 具体组件类实现接口,执行基本操作。
- 装饰器类持有组件的引用,并在执行基本操作时添加新的功能。
// 组件接口
class Component {
public:
virtual void operation() = 0;
};
// 具体组件
class ConcreteComponent : public Component {
public:
void operation() override {
std::cout << "ConcreteComponent operation\n";
}
};
// 抽象装饰类
class Decorator : public Component {
protected:
Component* component;
public:
Decorator(Component* comp) : component(comp) {}
void operation() override {
component->operation();
}
};
// 具体装饰类
class ConcreteDecorator : public Decorator {
public:
ConcreteDecorator(Component* comp) : Decorator(comp) {}
void operation() override {
Decorator::operation();
std::cout << "ConcreteDecorator added operation\n";
}
};
// 创建一个具体组件
Component* component = new ConcreteComponent();
// 装饰组件
Component* decorator = new ConcreteDecorator(component);
解释:通过具体装饰类传入原对象,并重写操作函数 operation()
来实现对象的功能扩展,ConcreteDecorator::operation
先执行对象原操作,再执行新扩展的功能。
策略模式
策略模式定义了一系列算法,将每个算法封装到一个独立的类中,使得它们可以相互替换。此模式允许算法的变化独立于使用它的客户端。常用于:算法选择、支付方式选择等。
实现方式:
- 定义一个抽象策略接口,声明策略的操作。
- 策略实现类负责具体的算法。
- 上下文类负责持有策略并执行操作。
// 抽象策略接口
class Strategy {
public:
virtual void execute() = 0;
};
// 策略实现类A
class ConcreteStrategyA : public Strategy {
public:
void execute() override {
std::cout << "Executing strategy A\n";
}
};
// 策略实现类B
class ConcreteStrategyB : public Strategy {
public:
void execute() override {
std::cout << "Executing strategy B\n";
}
};
// 上下文类
class Context {
private:
Strategy* strategy;
public:
Context(Strategy* strategy) : strategy(strategy) {}
// 选取某种策略
void setStrategy(Strategy* newStrategy) {
strategy = newStrategy;
}
// 执行选取策略的操作
void executeStrategy() {
strategy->execute();
}
};
代理模式
代理模式为其他对象提供一个代理,以控制对这个对象的访问。常见的应用场景包括虚拟代理(延迟加载)、远程代理(为远程对象提供本地代理),以及保护代理(控制对象的访问权限)。
实现方式:
- 定义一个接口,声明需要被代理的操作。
- 代理类实现接口,负责控制实际对象的访问。
- 实际对象类实现接口,执行具体操作。
class Subject {
public:
virtual void request() = 0;
};
// 实际对象类
class RealSubject : public Subject {
public:
void request() override {
std::cout << "RealSubject handling request\n";
}
};
// 代理类
class Proxy : public Subject {
private:
RealSubject* realSubject;
public:
Proxy() : realSubject(nullptr) {}
~Proxy() {
delete realSubject;
}
void request() override {
if (!realSubject) {
realSubject = new RealSubject();
}
std::cout << "Proxy handling request, forwarding to RealSubject...\n";
realSubject->request();
}
};
标签:void,观察者,C++,class,详解,模式,override,设计模式,public
From: https://blog.csdn.net/weixin_46571171/article/details/142756800