结构型设计模式

请添加图片描述

单例模式

定义

保证一个类仅有一个实例,并提供一个该实例的全局访问点——《设计模式》 GoF

版本一

缺点:不支持堆释放 不支持多线程

#include<iostream>
using namespace std;
class Singleton{
public:
    static Singleton* GetInstance(){
        if(_instance == NULL){
            _instance = new Singleton();
        }
        return _instance;
    }
private:
    Singleton(){}  //构造函数private 禁止访问
    ~Singleton(){} //防止delete
    Singleton(const Singleton &clonr){} //拷贝构造函数
    Singleton& operator=(const Singleton&){}
    static Singleton * _instance;
};
Singleton* Singleton::_instance = NULL;

版本二

堆对象释放问题

#include<iostream>
using namespace std;
//类对象之间 友元
class Singleton{
public:
    static Singleton* GetInstance(){
        if(_instance == NULL){
            _instance = new Singleton();
            atexit(Destructor);
        }
    }
private:
    static void Destructor(){ //静态成员函数只与类有关
        if(_instance != NULL){
            delete _instance;
            _instance = NULL;
        }
    }
    Singleton();
    ~Singleton();
    Singleton(const Singleton &cpy);
    Singleton& operator=(const Singleton& other){}
    static Singleton *_instance;
};
Singleton* Singleton::_instance = NULL;

版本三

多线程 3.1体现锁太重 3.2

#include<mutex>
using namespace std;

class Singleton{ //懒汉模式 lazy load
public:
    static Singleton* GetInstance(){
        //std::lock_guard<std::mutex> lock(_mutex);  //3.1切换线程
        if(_instance == NULL){
            std::lock_guard<std::mutex> lock(_mutex); //3.2
            if(_instance == NULL){
                _instance = new Singleton(); // 写操作
                //执行三个步骤
                //1. 分配内存
                //void operator new(size){
                //     return malloc(size);
                //}
                //2. 调用构造函数
                //3. 返回指针
                //多线程环境下 cpu reorder操作
                atexit(Destructor);
            }
        }
        return _instance; // 读操作
    }
private:
    static void Destructor(){
        if(_instance == NULL){
            delete _instance;
            _instance = NULL;
        }
    }
    Singleton();
    ~Singleton();
    Singleton& operator=(const Singleton&){}
    static Singleton* _instance;
    static std::mutex _mutex;
};
Singleton* Singleton::_instance = NULL;
std::mutex Singleton::_mutex;

版本四

//volitile
#include<iostream>
#include<atomic>
using namespace std;
class Singleton{
public:
    static Singleton* GetInstance(){
        Singleton* tmp = _instance.load(std::memory_order_relaxed);
        std::atomic_thread_fence(std::memory_order_acquire);
        if(tmp == nullptr){
            std::lock_guard<std::mutex> lock(_mutex);
            tmp = _insatnce.load(std::memory_order_relaxed);
            if(tmp == nullptr){
                tmp == new Singleton;
                std::atomic_thread_fence(std::memory_order_relaxed); //释放内存屏障
                _insatnce.store(tmp,std::memory_order_relaxed);
                atexit(Destructor);
            }
        }
        return tmp;
    }
private:
    static void Destructor(){
        Singleton*  tmp = _instance.load(std::memory_order_relaxed);
        if(nullptr == tmp){
            delete tmp;
        }
    }
    Singleton(){}
    ~Singleton(){}
    Singleton& operator=(const Singleton&){}
    static std::atomic<Singleton*> _instance;
    static std::mutex _mutex;
};

std::atomic<Singleton*> Singleton::_instance;
std::mutex Singleton::_mutex;

版本五

// c++11 magic static 特性:如果当变量在初始化的时候,并发同时进入声明语句并会阻塞等待初始化结束;
//c++ effective


class Singleton{
public:
    static Singleton& GetInstance(){
        static Singleton instance;
        return instance;
    }
private:
    Singleton(){}
    ~Singleton(){}
    Singleton(const Singleton&){}
    Singleton& operator=(const Singleton&){}
};

// 继承 Singleton
// g++ Singleton.cpp -o singleton -std=c++11

/*该版本具备 版本5 所有优点:
1. 利⽤静态局部变量特性,延迟加载;
2. 利⽤静态局部变量特性,系统⾃动回收内存,⾃动调⽤析构函数;
3. 静态局部变量初始化时,没有 new 操作带来的cpu指令reorder操作;
4. c++11 静态局部变量初始化时,具备线程安全;
*/

版本六

template<typename T>
class Singleton{
public:
    static  T& GetInstance(){
        static T instacne; // 初始化DesignPattern时会调用DesignPattern时会调用父类的构造函数
        return instance;
    }
protected:
    virtual ~Singleton(){}
    Singleton(){}
    Singleton(const Singleton&){}
    Singleton& operator=(const Singleton&){} 
};
class DesignPattern: public Singleton<DesignPattern>{
    friend class Singleton<DesignPattern>;
public:
    ~DesignPattern(){}
private:
    DesignPattern(){}
    DesignPattern(const DesignPattern&) {}
    DesignPattern& operator=(const DesignPattern&){}
};

结构图

请添加图片描述

工厂方法

定义

定义一个用于创建对象的接口,让子类觉点实例化哪一个类。Factory Method使得一个类的实例化延迟到子类。——《设计模式》GoF

背景

实现一个导出数据的接口,让客户选择数据导出方式。

要点

解决创建过程中比较复杂,希望对外隐藏这些细节的场景

  • 比如连接池、线程池
  • 隐藏对象真实类型
  • 对象创建会有很多参数来决定如何创建
  • 创建对象有复杂的依赖关系

本质

延迟到子类来选择实现。

代码

#include <string>
// 实现导出数据的接口, 导出数据的格式包含 xml,json,文本格式txt 后面可能扩展excel格式csv
class IExport {
public:
    virtual bool Export(const std::string &data) = 0;
    virtual ~IExport(){}
};

class ExportXml : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportJson : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};
// csv
class ExportTxt : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

// class ExportCSV : public IExport {
// public:
//     virtual bool Export(const std::string &data) {
//         return true;
//     }
// };

// =====1
int main() {
    std::string choose/* = */;
    if (choose == "txt") {
        /***/
        IExport *e = new ExportTxt();
        /***/
        e->Export("hello world");
    } else if (choose == "json") {
        /***/
        IExport *e = new ExportJson();
        /***/
        e->Export("hello world");
    } else if (choose == "xml") {
        IExport *e = new ExportXml();
        e->Export("hello world");
    } else if (choose == "csv") {
        IExport *e = new ExportXml();
        e->Export("hello world");
    }
}
#include <string>
// 实现导出数据的接口, 导出数据的格式包含 xml,json,文本格式txt 后面可能扩展excel格式csv
class IExport {
public:
    virtual bool Export(const std::string &data) = 0;
    virtual ~IExport(){}
};

class ExportXml : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportJson : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportTxt : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class IExportFactory {
public:
    virtual IExport * NewExport(/* ... */) = 0;
};

class ExportXmlFactory : public IExportFactory {
public:
    IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportXml;
        // 可能之后有什么操作
        return temp;
    }
};

class ExportJsonFactory : public IExportFactory {
public:
    IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportJson;
        // 可能之后有什么操作
        return temp;
    }
};

class ExportTxtFactory : public IExportFactory {
public:
    IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportTxt;
        // 可能之后有什么操作
        return temp;
    }
};

class ExportData {
public:
    ExportData(IExportFactory *factory) : _factory(factory) {}
    ~ExportData() {
        if (_factory) {
            delete _factory;
            _factory = nullptr;
        }
    }
    bool Export(const std::string &data) { // 稳定的流程 往基类放 
        IExport * e = _factory->NewExport();
        e->Export(data);
    }
private:
    IExportFactory *_factory;
};

int main() {
    ExportData ed(new ExportTxtFactory);
    ed.Export("hello world");
    return 0;
} 
#include <string>
// 实现导出数据的接口, 导出数据的格式包含 xml,json,文本格式txt 后面可能扩展excel格式csv
class IExport {
public:
    virtual bool Export(const std::string &data) = 0;
    virtual ~IExport(){}
};

class ExportXml : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportJson : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportTxt : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportCSV : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class IExportFactory {
public:
    IExportFactory() {
        _export = nullptr;
    }
    virtual ~IExportFactory() {
        if (_export) {
            delete _export;
            _export = nullptr;
        }
    }
    bool Export(const std::string &data) {
        if (_export == nullptr) {
            _export = NewExport();
        }
        return _export->Export(data);
    }
protected:
    virtual IExport * NewExport(/* ... */) = 0;
private:
    IExport* _export;
};

class ExportXmlFactory : public IExportFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportXml();
        // 可能之后有什么操作
        return temp;
    }
};
class ExportJsonFactory : public IExportFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportJson;
        // 可能之后有什么操作
        return temp;
    }
};
class ExportTxtFactory : public IExportFactory {
protected:
    IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportTxt;
        // 可能之后有什么操作
        return temp;
    }
};

class ExportCSVFactory : public IExportFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportCSV;
        // 可能之后有什么操作
        return temp;
    }
};

int main () {
    IExportFactory *factory = new ExportTxtFactory();
    factory->Export("hello world");
    return 0;
}

结构图

在这里插入图片描述

抽象工厂

定义

提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”。无需指定他们具体的类。——《设计模式》GoF

背景

实现一个拥有导入和导出数据的接口,让客户选择的数据的导出导入方式;

代码

#include <string>
// 实现导出数据的接口, 导出数据的格式包含 xml,json,文本格式txt 后面可能扩展excel格式csv
class IExport {
public:
    virtual bool Export(const std::string &data) = 0;
    virtual ~IExport(){}
};

class ExportXml : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportJson : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportTxt : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportCSV : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class IImport {
public:
    virtual bool Import(const std::string &data) = 0;
    virtual ~IImport(){}
};

class ImportXml : public IImport {
public:
    virtual bool Import(const std::string &data) {
        return true;
    }
};

class ImportJson : public IImport {
public:
    virtual bool Import(const std::string &data) {
        return true;
    }
};

class ImportTxt : public IImport {
public:
    virtual bool Import(const std::string &data) {
        return true;
    }
};

// 对于初学者: 知道扩展代码
// 5年
class ImportCSV : public IImport {
public:
    virtual bool Import(const std::string &data) {
        // ....
        return true;
    }
};

class IDataApiFactory {
public:
    IDataApiFactory() {
        _export = nullptr;
        _import = nullptr;
    }
    virtual ~IDataApiFactory() {
        if (_export) {
            delete _export;
            _export = nullptr;
        }
        if (_import) {
            delete _import;
            _import = nullptr;
        }
    }
    bool Export(const std::string &data) {
        if (_export == nullptr) {
            _export = NewExport();
        }
        return _export->Export(data);
    }
    bool Import(const std::string &data) {
        if (_import == nullptr) {
            _import = NewImport();
        }
        return _import->Import(data);
    }
protected:
    virtual IExport * NewExport(/* ... */) = 0;
    virtual IImport * NewImport(/* ... */) = 0;
private:
    IExport *_export;
    IImport *_import;
};

class XmlApiFactory : public IDataApiFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportXml;
        // 可能之后有什么操作
        return temp;
    }
    virtual IImport * NewImport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IImport * temp = new ImportXml;
        // 可能之后有什么操作
        return temp;
    }
};

class JsonApiFactory : public IDataApiFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportJson;
        // 可能之后有什么操作
        return temp;
    }
    virtual IImport * NewImport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IImport * temp = new ImportJson;
        // 可能之后有什么操作
        return temp;
    }
};
class TxtApiFactory : public IDataApiFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportTxt;
        // 可能之后有什么操作
        return temp;
    }
    virtual IImport * NewImport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IImport * temp = new ImportTxt;
        // 可能之后有什么操作
        return temp;
    }
};

class CSVApiFactory : public IDataApiFactory {
protected:
    virtual IExport * NewExport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IExport * temp = new ExportCSV;
        // 可能之后有什么操作
        return temp;
    }
    virtual IImport * NewImport(/* ... */) {
        // 可能有其它操作,或者许多参数
        IImport * temp = new ImportCSV;
        // 可能之后有什么操作
        return temp;
    }
};

// 相关性  依赖性    工作当中
int main () {
    IDataApiFactory *factory = new CSVApiFactory();
    factory->Import("hello world");
    factory->Export("hello world");
    return 0;
}

结构图

在这里插入图片描述

责任链

定义

使多个对象都有机会处理强求,从而比main请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,知道有一个对象处理它为。——《设计模式》GoF

背景

请求流程,1天内需要主程序批准,3天内需要项目经理批准,3天以上需要老板批准

变化点: 天数、处理链长度

稳定点:处理流程

要点

  • 解耦请求方和处理方,请求方不知道请求是如何被处理,处理方的组成是由相互独立的子处理构成,子处理流程通过链表方式连接,子处理请求流程可以按任意顺序组合;
  • 责任链请求强调请求最终由一个字处理流程处理;通过了各个字处理条件判断;
  • 责任链扩展就是功能链,功能链强调的是,一个请求依次经由功能链中的子处理流程处理;
  • 将职责以及指责顺序运行进行抽象,那么指责变化可以任意扩展,同时指责顺序也可以任意扩展;

本质

分离职责,动态组合

代码

#include <string>

class Context {
public:
    std::string name;
    int day;
};

// 稳定点 和 变化点
// 稳定点:批假流程   由职位从低到高批假  有权限
// 变化点:请假天数、增加批假人员
// 在一个整洁的房子(稳定点),好动的猫(变化),怎么保证这个房子的整洁?
// 把猫放在笼子里
// 如果某一个需求 只有稳定点  不需要设计模式(应对变化的)
// 如果全是变化点,也不需要设计模式?软件开发怎么解决全是变化点?脚本语言 热更新 来应对变化点
// 如果两者都存在,不是消灭变化点,是隔离变化点   解耦合
// 多线程锁  锁的类型  锁的粒度 线程池  
class LeaveRequest {
public:
    bool HandleRequest(const Context &ctx) {
        if (ctx.day <= 1)
            HandleByBeaty(ctx);
        if (ctx.day <= 1)
            HandleByMainProgram(ctx);
        else if (ctx.day <= 10)
            HandleByProjMgr(ctx);
        else
            HandleByBoss(ctx);
    }

public:
    bool HandleByBeaty(const Context &ctx) {
        
    }
    bool HandleByMainProgram(const Context &ctx) {
        
    }
    bool HandleByProjMgr(const Context &ctx) {
        
    }
    bool HandleByBoss(const Context &ctx) {

    }
};

结构图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AIhdkvck-1679144749458)(D:\zwc\c++\ls\designpattern\img\12.cpp)]

装饰器

定义

动态地给一个对象增加一些额外的职责。就增加功能而言,装饰器模式比生产子类更为灵活。——《设计模式》GoF

背景

普通员工有销售奖金、累计奖金,部门经理除此之外还有团队奖金;后面还可能会增加环比增加奖金,同时可能针对不同职位产生不同的奖金组合。——《设计模式》GoF

稳定点:扩展流程

变化点:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a3eqROFP-1679144749458)(D:\zwc\c++\ls\designpattern\img\13.png)]

代码

// 普通员工有销售奖金,累计奖金,部门经理除此之外还有团队奖金;后面可能会添加环比增长奖金,同时可能产生不同的奖金组合;
// 销售奖金 = 当月销售额 * 4%
// 累计奖金 = 总的回款额 * 0.2%
// 部门奖金 = 团队销售额 * 1%
// 环比奖金 = (当月销售额-上月销售额) * 1%
// 销售后面的参数可能会调整
class Context {
public:
    bool isMgr;
    // User user;
    // double groupsale;
};

class Bonus {
public:
    double CalcBonus(Context &ctx) {
        double bonus = 0.0;
        bonus += CalcMonthBonus(ctx);
        bonus += CalcSumBonus(ctx);
        if (ctx.isMgr) {
            bonus += CalcGroupBonus(ctx);
        }
        return bonus;
    }
private:
    double CalcMonthBonus(Context &ctx) {
        double bonus/* = */;
        return bonus;
    }
    double CalcSumBonus(Context &ctx) {
        double bonus/* = */;
        return bonus;
    }
    double CalcGroupBonus(Context &ctx) {
        double bonus/* = */;
        return bonus;
    }
};

int main() {
    Context ctx;
    // 设置 ctx
    Bonus *bonus = new Bonus;
    bonus->CalcBonus(ctx);
}
#include <iostream>
// 普通员工有销售奖金,累计奖金,部门经理除此之外还有团队奖金;后面可能会添加环比增长奖金,同时可能产生不同的奖金组合;
// 销售奖金 = 当月销售额 * 4%
// 累计奖金 = 总的回款额 * 0.2%
// 部门奖金 = 团队销售额 * 1%
// 环比奖金 = (当月销售额-上月销售额) * 1%
// 销售后面的参数可能会调整
using namespace std;
class Context {
public:
    bool isMgr;
    // User user;
    // double groupsale;
};


class CalcBonus {    
public:
    CalcBonus(CalcBonus * c = nullptr) : cc(c) {}
    virtual double Calc(Context &ctx) {
        return 0.0; // 基本工资
    }
    virtual ~CalcBonus() {}

protected:
    CalcBonus* cc;
};

class CalcMonthBonus : public CalcBonus {
public:
    CalcMonthBonus(CalcBonus * c) : CalcBonus(c) {}
    virtual double Calc(Context &ctx) {
        double mbonus /*= 计算流程忽略*/; 
        return mbonus + cc->Calc(ctx);
    }
};

class CalcSumBonus : public CalcBonus {
public:
    CalcSumBonus(CalcBonus * c) : CalcBonus(c) {}
    virtual double Calc(Context &ctx) {
        double sbonus /*= 计算流程忽略*/; 
        return sbonus + cc->Calc(ctx);
    }
};

class CalcGroupBonus : public CalcBonus {
public:
    CalcGroupBonus(CalcBonus * c) : CalcBonus(c) {}
    virtual double Calc(Context &ctx) {
        double gbnonus /*= 计算流程忽略*/; 
        return gbnonus + cc->Calc(ctx);
    }
};

class CalcCycleBonus : public CalcBonus {
public:
    CalcCycleBonus(CalcBonus * c) : CalcBonus(c) {}
    virtual double Calc(Context &ctx) {
        double gbnonus /*= 计算流程忽略*/; 
        return gbnonus + cc->Calc(ctx);
    }
};

int main() {
    // 1. 普通员工
    Context ctx1;
    CalcBonus *base = new CalcBonus();
    CalcBonus *cb2 = new CalcSumBonus(base);
    CalcBonus *cb1 = new CalcMonthBonus(cb2);


    cb2->Calc(ctx1);
    // 2. 部门经理
    Context ctx2;
    CalcBonus *cb3 = new CalcGroupBonus(cb2);
    cb3->Calc(ctx2);
}

virtual double Calc(Context &ctx) {
double sbonus /= 计算流程忽略/;
return sbonus + cc->Calc(ctx);
}
};

class CalcGroupBonus : public CalcBonus {
public:
CalcGroupBonus(CalcBonus * c) : CalcBonus© {}
virtual double Calc(Context &ctx) {
double gbnonus /= 计算流程忽略/;
return gbnonus + cc->Calc(ctx);
}
};

class CalcCycleBonus : public CalcBonus {
public:
CalcCycleBonus(CalcBonus * c) : CalcBonus© {}
virtual double Calc(Context &ctx) {
double gbnonus /= 计算流程忽略/;
return gbnonus + cc->Calc(ctx);
}
};

int main() {
// 1. 普通员工
Context ctx1;
CalcBonus *base = new CalcBonus();
CalcBonus *cb2 = new CalcSumBonus(base);
CalcBonus *cb1 = new CalcMonthBonus(cb2);

cb2->Calc(ctx1);
// 2. 部门经理
Context ctx2;
CalcBonus *cb3 = new CalcGroupBonus(cb2);
cb3->Calc(ctx2);

}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值