设计模式简述(二)

单例模式

定义:旨在确保类只有一个实例,并提供一个全局访问点来访问该实例。单例模式通常用于需要在整个应用程序中共享相同对象实例的情况,例如全局配置对象、日志对象、数据库连接等。

人话:只在程序程序运行的时候初始化一次,初始化完成之后无论是再执行构造、拷贝构造、移动拷贝构造都不会新创建一个对象。c++最简单的就是使用static修饰类初始化函数和成员变量,因为static在c++中是线程安全的,但是注意在其它语言中不一定。

demo:

public class Singleton {
    private static Singleton instance;

    private Singleton() {
        // 私有化构造函数,防止外部实例化
    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

工厂模式

定义:封装对象的创建过程,使得客户端代码不需要直接实例化对象,而是通过工厂类来创建对象。

demo:

#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 ExportCSVFactory();
    factory->Export("hello world");
    return 0;
}

抽象工厂

定义:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

人话:工厂模式的升级版本,写程序的时候可能有若干个工厂,实现一个工厂创造器/生成器类,获取具体工厂,再通过具体工厂获取实例化的类对象。有条件把所有工厂的结构进行抽象,抽象出一个基类,所有工厂继承自这个基类。

# 抽象产品A
class AbstractProductA:
    def operation(self):
        pass

# 具体产品A1
class ConcreteProductA1(AbstractProductA):
    def operation(self):
        return "Product A1 operation"

# 具体产品A2
class ConcreteProductA2(AbstractProductA):
    def operation(self):
        return "Product A2 operation"

# 抽象产品B
class AbstractProductB:
    def operation(self):
        pass

# 具体产品B1
class ConcreteProductB1(AbstractProductB):
    def operation(self):
        return "Product B1 operation"

# 具体产品B2
class ConcreteProductB2(AbstractProductB):
    def operation(self):
        return "Product B2 operation"

# 抽象工厂
class AbstractFactory:
    def create_product_a(self):
        pass

    def create_product_b(self):
        pass

# 具体工厂1
class ConcreteFactory1(AbstractFactory):
    def create_product_a(self):
        return ConcreteProductA1()

    def create_product_b(self):
        return ConcreteProductB1()

# 具体工厂2
class ConcreteFactory2(AbstractFactory):
    def create_product_a(self):
        return ConcreteProductA2()

    def create_product_b(self):
        return ConcreteProductB2()

# 客户端代码
factory_type = 1
if factory_type == 1:
    factory = ConcreteFactory1()
elif factory_type == 2:
    factory = ConcreteFactory2()

product_a = factory.create_product_a()
product_b = factory.create_product_b()

print(product_a.operation())  # Output: Product A1 operation
print(product_b.operation())  # Output: Product B1 operation

责任链

定义:许多个对象都有机会处理请求,从而避免请求的发送者与接收者之间的直接耦合。在责任链模式中,请求沿着一个链传递,直到有一个对象处理它为止。

人话:把处理对象封装在一个函数或者类的内部,然后按照执行这些处理对象,每个处理对象可能解决部分问题,直到问题被全部解决。

demo:

#include <memory>
#include <string>

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

// 稳定点 抽象  变化点 扩展 (多态)
//  从单个处理节点出发,我能处理,我处理,我不能处理交给下一个人处理
//  链表关系如何抽象

class HandleByMainProgram;
class HandleByProjMgr;
class HandleByBoss;
class HandleByBeauty;

class IHandler {
public:
    IHandler() : next(nullptr) {}
    virtual ~IHandler();
    void SetNextHandler(IHandler *next) { // 链表关系
        next = next;
    }
    bool Handle(const Context &ctx) {
        if (CanHandle(ctx)) {
            return HandleRequest(ctx);
        } else if (GetNextHandler()) {
            return GetNextHandler()->Handle(ctx);
        } else {
            // err
        }
        return false;
    }
protected:
    virtual bool HandleRequest(const Context &ctx) = 0;
    virtual bool CanHandle(const Context &ctx) = 0;
    IHandler * GetNextHandler() {
        return next;
    }
private:
    IHandler *next; // 组合基类指针
};


class Request {
public:
    Request() {
        IHandler * h0 = new HandleByBeauty();
        IHandler * h1 = new HandleByMainProgram();
        IHandler * h2 = new HandleByProjMgr();
        IHandler * h3 = new HandleByBoss();
        h0->SetNextHandler(h1);
        h1->SetNextHandler(h2);
        h2->SetNextHandler(h3);
        handler = h0;
    }
    bool Handle(const Context &ctx) {
        return handler->Handle(ctx);
    }
private:
    IHandler *handler;
};

class HandleByMainProgram : public IHandler {
protected:
    virtual bool HandleRequest(const Context &ctx){
        //
        return true;
    }
    virtual bool CanHandle(const Context &ctx) {
        //
        if (ctx.day <= 1)
            return true;
        return false;
    }
};

class HandleByProjMgr : public IHandler {
protected:
    virtual bool HandleRequest(const Context &ctx){
        //
        return true;
    }
    virtual bool CanHandle(const Context &ctx) {
        //
        if (ctx.day <= 20)
            return true;
        return false;
    }
};
class HandleByBoss : public IHandler {
protected:
    virtual bool HandleRequest(const Context &ctx){
        //
        return true;
    }
    virtual bool CanHandle(const Context &ctx) {
        //
        if (ctx.day < 30)
            return true;
        return false;
    }
};

class HandleByBeauty : public IHandler {
protected:
    virtual bool HandleRequest(const Context &ctx){
        //
        return true;
    }
    virtual bool CanHandle(const Context &ctx) {
        //
        if (ctx.day <= 3)
            return true;
        return false;
    }
};

int main() {
// 抽象工厂
// nginx http 处理 
    // 设置下一指针 
    Context ctx;
    auto req = std::make_unique<Request>();
    req->Handle(ctx);
    
    return 0;
}

装饰器

定义:过组合和递归组合的方式来动态地增加对象的功能,而不是通过修改现有类的接口来实现功能的扩展。

人话:在不改变原有接口的基础上通过组合、继承等手段重写或扩展原始对象的方法。

demo:

#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 *cb1 = new CalcMonthBonus(base);
    CalcBonus *cb2 = new CalcSumBonus(cb1);


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

组合模式

定义:又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

人话:类的嵌套,把相似的类存储到一个容器中,一般容器对象和叶子对象通常实现同一个接口或继承同一个抽象类

demo:

class IComponent
{
public:
    IComponent(/* args */);
    ~IComponent();
    virtual void Execute() = 0;
    virtual void AddChild(IComponent *ele) {}
    virtual void RemoveChild(IComponent *ele) {}
};

class Leaf : public IComponent{
public:
    virtual void Execute() {
        cout << "leaf exxcute" << endl;
    }
};

class Composite : public IComponent
{
private:
    std::list<IComponent*> _list;
public:
    virtual void AddChild(IComponent *ele) {
        // ...
    }
    virtual void RemoveChild(IComponent *ele) {
        // ...
    }
    virtual void Execute() {
        for (auto iter = _list.begin(); iter != _list.end(); iter++) {
            iter->Execute();
        }
    }
};


适配器

定义:主要目的是将一个接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以协同工作

demo:

#include <iostream>
#include <string>

// MP3播放器接口
class MP3Player {
public:
    virtual ~MP3Player() {}
    virtual void play(const std::string& audioFilePath) = 0;
};

// WAV播放器类
class WAVPlayer {
public:
    void playWAV(const std::string& wavFilePath) {
        std::cout << "Playing WAV file: " << wavFilePath << std::endl;
    }
};

// WAV转MP3适配器
class WAVtoMP3Adapter : public MP3Player {
private:
    WAVPlayer wavPlayer;

public:
    void play(const std::string& audioFilePath) override {
        // 假设音频文件名后缀转换逻辑,实际上应根据实际情况调整
        std::string convertedFilePath = audioFilePath.substr(0, audioFilePath.find_last_of('.')) + ".wav";
        wavPlayer.playWAV(convertedFilePath);
    }
};

int main() {
    // 创建适配器实例,模拟播放MP3文件
    WAVtoMP3Adapter adapter;

    // 尝试播放一个"MP3"文件,实际上通过适配器播放WAV
    adapter.play("favorite_song.mp3");

    return 0;
}

这是一条吃饭博客,由挨踢零声赞助。学C/C++就找挨踢零声,加入挨踢零声,面试不挨踢!

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值