设计模式(一)
设计模式(二)
单例模式(Singleton)
保证一个类仅有一个实例,并且提供一个该实例的全局访问点
稳定点:类只有一个实例
变化点:没啥
要点:要把构造函数禁掉(私有化)
产生构造的方式有:
//拷贝构造
A (const A&) = delete;
//拷贝赋值构造
A& operator=(const A&) = delete;
版本一(懒汉模式----线程不安全版)
#include <iostream>
class A {
private:
// 静态私有成员变量,用于保存类的唯一实例
static A* instance;
// 私有构造函数,防止外部通过new创建多个实例
A() {};
~A() {};
// 禁止拷贝构造函数和赋值操作符,防止复制和赋值
A(const A&) = delete;
A& operator=(const A&) = delete;
public:
// 静态公有方法,提供全局访问点
static A* getInstance() {
if (instance == nullptr) {
//此处线程不安全!!!!!!!!!!!!!!!!
instance = new A();
}
return instance;
}
};
// 初始化静态成员变量
A* A::instance = nullptr;
问题:线程不安全(多线程会创造多个实例)
版本二
#include <iostream>
#include <mutex>
class A {
private:
// 静态私有成员变量,用于保存类的唯一实例
static A* instance;
static std::mutex mutex;//添加互斥锁
// 私有构造函数,防止外部通过new创建多个实例
A() {};
~A() {};
// 禁止拷贝构造函数和赋值操作符,防止复制和赋值
A(const A&) = delete;
A& operator=(const A&) = delete;
public:
// 静态公有方法,提供全局访问点
static A* getA() {
std::lock_guard<std::mutex> lock(mutex); // 锁定互斥锁
if (instance == nullptr) {
instance = new A();
}
return instance;
}
};
// 初始化静态成员变量
A* A::instance = nullptr;
问题:每次都要上锁,效率低
版本三
#include <iostream>
#include <mutex>
class A {
private:
// 静态私有成员变量,用于保存类的唯一实例
static A* instance;
static std::mutex mutex;//添加互斥锁
// 私有构造函数,防止外部通过new创建多个实例
A() {};
~A() {};
// 禁止拷贝构造函数和赋值操作符,防止复制和赋值
A(const A&) = delete;
A& operator=(const A&) = delete;
public:
// 静态公有方法,提供全局访问点
static A* getA() {
if(instance == nullptr)//double check保证效率
{
std::lock_guard<std::mutex> lock(mutex);
if (instance == nullptr) {
instance = new A();
}
}
return instance;
}
};
// 初始化静态成员变量
A* A::instance = nullptr;
问题:没有考虑现在多核时代指令重排问题
在 instance = new A();
时,实际上执行了三条指令
- 分配内存 2. 调用构造函数A() 3. 返回指针给instance
那么如果指令重排为1 3 2,在完成1 3 后切换了另一个进程访问,此时发现instance!= nullptr
如果此时该进程要对instance进行操作,但是实际上步骤2还没有用构造函数创建A,就会发送程序崩溃。
版本四
#include <iostream>
class A {
private:
// 私有构造函数,防止外部通过new创建多个实例
A() {};
~A() {};
// 禁止拷贝构造函数和赋值操作符,防止复制和赋值
A(const A&) = delete;
A& operator=(const A&) = delete;
public:
// 静态公有方法,提供全局访问点
static A& getInstance() {
//直接构造,static不会指令重排,线程安全
static A instance;
return instance;
}
};
问题:虽然上述问题都解决了,但是代码复用性差
版本五
#include <iostream>
template<typename T>
class A {//基类
private:
// 禁止拷贝构造函数和赋值操作符,防止复制和赋值
A(const A&) = delete;
A& operator=(const A&) = delete;
protected://要让子类能调用
virtual ~A(){}
A() {};//protected
public:
// 静态公有方法,提供全局访问点
static T& getInstance() {
//直接构造,static不会指令重排,线程安全
static T instance;
return instance;
}
};
class D : public A<D>{
friend class A<D>;
private:
D{};
~D{};
};
实际熟悉版本一,三,四就差不多
工厂方法模式(Factory Method)
定义一个用于创建对象的接口,让子类决定实例化哪一个类,FactoryMethod使得一个类的实例化延迟到了子类
稳定点:创建同类对象的接口,同类对象有一个相同的职责
变化点:创建对象的拓展,对象的增加
实现一个到处数据的接口,让用户选择数据导出的方式
#include <iostream>
#include <string>
#include <memory>
// 数据导出接口
class DataExporter {
public:
virtual ~DataExporter() {}
virtual void exportData(const std::string& data) = 0;
};
// 具体的数据导出类
class CSVExporter : public DataExporter {
public:
void exportData(const std::string& data) override {
std::cout << "Exporting data as CSV: " << data << std::endl;
}
};
class JSONExporter : public DataExporter {
public:
void exportData(const std::string& data) override {
std::cout << "Exporting data as JSON: " << data << std::endl;
}
};
class XMLExporter : public DataExporter {
public:
void exportData(const std::string& data) override {
std::cout << "Exporting data as XML: " << data << std::endl;
}
};
// 工厂类
class DataExporterFactory {
public:
static std::unique_ptr<DataExporter> createExporter(const std::string& type) {
if (type == "csv") {
return std::make_unique<CSVExporter>();
} else if (type == "json") {
return std::make_unique<JSONExporter>();
} else if (type == "xml") {
return std::make_unique<XMLExporter>();
} else {
throw std::invalid_argument("Unknown exporter type");
}
}
};
抽象工厂模式(Abstract Factory)
提供一个接口,让该接口负责创建一系列“相关或相互依赖的对象”,无需指定他们具体的类
稳定点:创建同类对象接口 对象创建接口
变化点:同类对象有多个相同的职责 功能接口
责任链模式(Chain of Responsibility Pattern)
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并且沿着这条链传递,直到有个对象处理它为止。
稳定点:处理流程
变化点:新增加处理流程,调整处理顺序
#include <iostream>
using namespace std;
//请求类
class PurchaseRequest
{
public:
int getType() const
{
return type;
}
float getPrice() const
{
return price;
}
int getId() const
{
return id;
}
PurchaseRequest(const int type, const float price, const int id)
: type(type),
price(price),
id(id)
{
}
private:
//请求类型
int type;
//价格
float price = 0.f;
int id = 0;
};
class Approver
{
public:
void setApprover(Approver* const approver)
{
this->approver = approver;
}
explicit Approver(const string& name)
: name(name)
{
}
//处理审批请求的方法,得到一个请求,处理是子类完成的,因此该方法写成纯虚方法
virtual void processRequest(PurchaseRequest* purchaseRequest)=0;
protected:
//下一个处理者
Approver* approver;
//名字
string name;
};
//教学主任
class DepartmentApprover:public Approver
{
public:
explicit DepartmentApprover(const string& name)
: Approver(name)
{
}
void processRequest(PurchaseRequest* purchaseRequest) override
{
if(purchaseRequest->getPrice()<=5000)
{
cout << "请求编号id=" << purchaseRequest->getId() << "被" << this->name << "处理" << endl;
}
else
{
approver->processRequest(purchaseRequest);
}
}
};
//院长
class CollegeApprover :public Approver
{
public:
explicit CollegeApprover(const string& name)
: Approver(name)
{
}
void processRequest(PurchaseRequest* purchaseRequest) override
{
if (purchaseRequest->getPrice() > 5000 && purchaseRequest->getPrice() <= 10000)
{
cout << "请求编号id=" << purchaseRequest->getId() << "被" << this->name << "处理" << endl;
}
else
{
approver->processRequest(purchaseRequest);
}
}
};
//副校长
class ViceSchoolMasterApprover :public Approver
{
public:
explicit ViceSchoolMasterApprover(const string& name)
: Approver(name)
{
}
void processRequest(PurchaseRequest* purchaseRequest) override
{
if (purchaseRequest->getPrice() > 10000 && purchaseRequest->getPrice() <= 30000)
{
cout << "请求编号id=" << purchaseRequest->getId() << "被" << this->name << "处理" << endl;
}
else
{
approver->processRequest(purchaseRequest);
}
}
};
//校长
class SchoolMasterApprover :public Approver
{
public:
explicit SchoolMasterApprover(const string& name)
: Approver(name)
{
}
void processRequest(PurchaseRequest* purchaseRequest) override
{
if (purchaseRequest->getPrice() > 30000)
{
cout << "请求编号id=" << purchaseRequest->getId() << "被" << this->name << "处理" << endl;
}
else
{
approver->processRequest(purchaseRequest);
}
}
};
int main(int argc, char* argv[])
{
//创建一个请求
PurchaseRequest* purchaseRequest = new PurchaseRequest(1, 1000, 1);
//创建相关的审批人
DepartmentApprover* department = new DepartmentApprover("张主任");
CollegeApprover* college = new CollegeApprover("李院长");
ViceSchoolMasterApprover* viceSchoolMaster = new ViceSchoolMasterApprover("王副校长");
SchoolMasterApprover* schoolMaster = new SchoolMasterApprover("佟校长");
//需要将各个审批级别的下一个人设置好(处理人构成一个环装就可以从任何一个人开始处理了)
//否则必须从第一个处理人开始
department->setApprover(college);
college->setApprover(viceSchoolMaster);
viceSchoolMaster->setApprover(schoolMaster);
schoolMaster->setApprover(department);
//开始处理请求
viceSchoolMaster->processRequest(purchaseRequest);
return 0;
}
装饰器模式(Decorator)
允许用户在不修改对象本身的情况下动态地给单个对象添加额外的职责。
稳定点:抽象组件接口–具体组件–装饰器接口
变化点:具体装饰器
#include <iostream>
#include <string>
// 抽象组件
class Component {
public:
virtual void operation() = 0; // 纯虚函数
virtual ~Component() {} // 虚析构函数
};
// 具体组件
class ConcreteComponent : public Component {
public:
void operation() override {
std::cout << "ConcreteComponent operation" << std::endl;
}
};
// 抽象装饰器
class Decorator : public Component {
protected:
Component* component; // 持有组件的引用
public:
Decorator(Component* component) : component(component) {}
virtual void operation() override {
if (component) {
component->operation();
}
}
};
// 具体装饰器A
class ConcreteDecoratorA : public Decorator {
public:
ConcreteDecoratorA(Component* component) : Decorator(component) {}
void operation() override {
Decorator::operation();
addBehavior();
}
void addBehavior() {
std::cout << " Added behavior A" << std::endl;
}
};
// 具体装饰器B
class ConcreteDecoratorB : public Decorator {
public:
ConcreteDecoratorB(Component* component) : Decorator(component) {}
void operation() override {
Decorator::operation();
addBehavior();
}
void addBehavior() {
std::cout << " Added behavior B" << std::endl;
}
};
int main() {
Component* simple = new ConcreteComponent();
simple->operation();
Component* decoratedA = new ConcreteDecoratorA(simple);
decoratedA->operation();
Component* decoratedAB = new ConcreteDecoratorB(decoratedA);
decoratedAB->operation();
delete simple;
delete decoratedA;
delete decoratedAB;
return 0;
}