0,简介

        设计模式共有23种,并不全讲,主要针对实际开发中使用频率较高的设计模式进行总结。

        设计模式的基础包含 面向对象的思想(封装继承多态)以及 设计原则(OOD经典原则和常用基础原则)。 重点是掌握【设计模式的学习步骤】。

了解设计模式解决的问题:分析稳定点、变化点(扩展部分)

实际开发中尽量写少量的代码应对各种场景

了解设计模式的结构,有思路,快速反应

抽象思考符合哪些设计原则,帮助自己养成好习惯

设计模式和工作需求、场景的联系(记住典型应用场景比较好)

重要的是如何扩展

动态多态很重要,大量设计模式要用

1,模板方法

关注设计原则:1,设计模式由设计原则演变     2,符合设计原则的代码,只需要修改少量代码就可以演变成设计模式

       用扩展(继承多态)的方式限定变化点方向;用 protected 对其他用户关闭(防止随意修改),但是对子类开放(创新替换);用 virtual 是为了多态的使用,子类中复写虚函数实现功能 (使用方式是多态的使用方式:基类指针指向一个 new 的子类对象)

        主要思路:把不变的代码部分转移到父类中,将可变的代码用 virtual 留到子类重写。

#include<iostream>
#include <vector>
#include <string>
using namespace std;

class AbstractClass
{
public:
    void Show()
    {
        cout<<"我是"<<GetName()<<endl;
    }
protected:
    virtual string GetName()=0;
};

class Naruto : public AbstractClass
{
protected:
    virtual string GetName()
    {
        return "火影史上最帅的六代目---一鸣惊人 naruto";
    }
};

class OnePice : public AbstractClass
{
protected:    
    virtual string GetName()
    {
    return "我是无恶不做的大海贼---路飞";
    }
};

//客户端
int main()
{
    Naruto* man = new Naruto();
    man->Show();
    OnePice* man2 = new OnePice();
    man2->Show();
    return 0;
}

2,观察者模式

用面向接口编程,继承接口;应对稳定点用抽象,应对变化点用继承和组合

         主要思路:让多个观察对象同时监听一个主题对象,主题对象状态发生变化时,会通知所有的观察者,使它们能够更新自己

#include <string>
#include <iostream>
#include <vector>
using namespace std;

class Secretary;

//看股票的同事类(观察对象,观察者)
class StockObserver
{
private:
    string name;
    Secretary* sub;
public:
    StockObserver(string strname,Secretary* strsub)
    {
        name=strname;
        sub=strsub;
    }
    void Update();
};

//秘书类(主题对象,通知者)
class Secretary
{
private:
    vector<StockObserver*> observers;
public:
    string action;
    void Add(StockObserver* ob)
    {
        if (ob != nullptr) {
            observers.push_back(ob);
        }
    }
    void Minus(StockObserver * ob) {
        //
        auto it = remove(observers.begin(), observers.end(), ob);
        if (it != observers.end()) {
            observers.erase(it, observers.end()); 
         }
    }
    void Notify()
    {
        vector<StockObserver*>::iterator p = observers.begin();
        while (p!=observers.end())
        {
            (*p)->Update();
            p++;
        }
    }

};

void StockObserver::Update()  //类的成员函数分离式定义
{
    cout<<name<<":"<<sub->action<<",不要玩股票了,要开始工作了"<<endl;
}

//客户端
int main()
{
    Secretary *p=new Secretary(); //创建通知者

    //观察者
    StockObserver *s1= new StockObserver("小李",p);
    StockObserver *s2 = new StockObserver("小赵",p);

    //加入通知队列
    p->Add(s1);
    p->Add(s2);
    //事件
    p->action="老板来了";
    //通知
    p->Notify();

    //退出通知队列
    p->Minus(s2);
    p->action="老板来了";
    //通知
    p->Notify();
    return 0;
}

3,策略模式

  • 稳定点:抽象去解决它
  • 变化点:扩展(继承和组合)去解决它

        主要思路:类中的成员以方法为主,算法可经常变动;简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。(不足:客户端要做判断)【解决:用策略工厂类创建对应的具体运算策略对象,代码中功能集成在 Context 类中。】

#include <iostream>
using namespace std;

//策略基类
class COperation
{
public:
    int m_nFirst;
    int m_nSecond;

    virtual double GetResult()
    {
        double dResult = 0;
        return dResult;
    }
};

//策略具体类—加法类
class AddOperation : public COperation
{
public:
    AddOperation(int a, int b)
    {
        m_nFirst = a;
        m_nSecond = b;
    }

    virtual double GetResult() override
    {
        return m_nFirst + m_nSecond;
    }
};

class SubOperation : public COperation
{
public:
    SubOperation(int a, int b)
    {
        m_nFirst = a;
        m_nSecond = b;
    }

    virtual double GetResult() override
    {
        return m_nFirst - m_nSecond;
    }
};

class Context
{
private:
    COperation* op;

public:
    // 修改构造函数:接收运算符 + 两个运算数,支持用户输入
    Context(char cType, int a, int b)
    {
        switch (cType)
        {
            case '+':
                op = new AddOperation(a, b);
                break;
            case '-':
                op = new SubOperation(a, b);
                break;
            // 默认情况:创建加法对象(也可设为 nullptr 做安全处理)
            default:
                op = new AddOperation(a, b);
                break;
        }
    }
    // 对外统一接口:获取运算结果
    double GetResult()
    {
        return op->GetResult();
    }

    ~Context()
    {
        if (op != nullptr)
        {
            delete op;
            op = nullptr;
        }
    }
};

int main()
{
    int a, b;
    char c;

    cout << "请输入两个整数(用空格分隔):" << endl;
    cin >> a >> b;

    cout << "请输入运算符(+、-):" << endl;
    cin >> c;

    // 创建 Context 对象,传递运算符和用户输入的运算数
    Context *test = new Context(c, a, b);
    cout << "运算结果:" << test->GetResult() << endl;

    delete test;
    test = nullptr;
    return 0;
}

4,单例模式

使用场景:资源独占 创建成本高(连接池、硬件操作);全局配置 状态需统一共享;全局统一服务。 核心原则:解决多个实例带来的问题(资源浪费、数据不一致)

        主要思路:保证一个类仅有一个实例,并提供一个该实例的全局访问点

#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Singleton{
private:
    static Singleton* single;

public:
    static Singleton* GetInstance()
    {
        if(single == NULL)
        {
            single = new Singleton();
        }
        return single;
    }
private:
    static void Destructor() {
        if (nullptr != _instance) { //
            delete _instance;
            _instance = nullptr;
        }
    }
    Singleton(){}; //构造
    ~Singleton(){}; //析构
    Singleton(const Singleton &) = delete; //拷⻉构造
    Singleton& operator=(const Singleton&) =
delete;//拷贝赋值构造
    Singleton(Singleton &&) = delete;//移动构造
    Singleton& operator=(Singleton &&) =
delete;//移动拷贝构造
    static Singleton * _instance;
};

Singleton* Singleton::single = NULL;  //注意静态变量类外初始化

int main()
{
    Singleton* s1 = Singleton::GetInstance();
    Singleton* s2 = Singleton::GetInstance();
    if(s1==s2)
        cout << "ok" << endl;
    else
        cout << "no" << endl;

    return 0;
}

用C++11 magic static特性写出 线程安全、不重排指令 的精简代码;

应对变化点的需求:加上多态(帮助复用),用模板甲基橙的方式实现。

// 模板单例基类(迈耶斯单例,C++11及以上线程安全)
template<typename T>
class Singleton {
public:
    // 静态方法:获取唯一的T类型实例(核心逻辑)
    static T& GetInstance() {
        // 局部静态变量:
        // 1. C++11标准规定:局部静态变量的初始化是线程安全的,由编译器保证只被初始化一次
        // 2. 首次调用GetInstance()时才初始化,实现“懒加载”(按需创建)
        // 3. 初始化时会调用T的构造函数,若T有父类,会自动链式调用父类构造函数
        static T instance;
        
        // 返回引用(避免拷贝,同时保证全局唯一;若返回指针可能被外部误delete)
        return instance;
    }

protected:
    // 保护的析构函数:
    // 1. 允许子类(T)继承Singleton,子类析构时能正常调用
    // 2. 禁止外部直接通过Singleton<T>指针调用析构(防止非法销毁)
    virtual ~Singleton() {}

    // 保护的构造函数:
    // 1. 禁止外部直接创建Singleton<T>对象(符合单例要求)
    // 2. 允许子类(T)访问,因为子类需要继承该基类
    Singleton() {}

private:
    // 禁用所有拷贝、移动语义,防止通过拷贝/移动创建新实例,保证全局唯一
    Singleton(const Singleton &) = delete;            // 拷贝构造函数(禁用)
    Singleton& operator=(const Singleton&) = delete;  // 拷贝赋值运算符(禁用)
    Singleton(Singleton &&) = delete;                 // 移动构造函数(禁用)
    Singleton& operator=(Singleton &&) = delete;      // 移动赋值运算符(禁用)
};

// 业务类:继承通用单例基类,成为单例类
class DesignPattern : public Singleton<DesignPattern> {
    // 声明友元类:
    // 让Singleton<DesignPattern>能够访问DesignPattern的私有构造/析构函数
    // 因为Singleton::GetInstance()中需要创建T(即DesignPattern)的实例,而DesignPattern的构造是私有的
    friend class Singleton<DesignPattern>;

private:
    // 私有构造函数:
    // 1. 禁止外部直接创建DesignPattern对象,符合单例要求
    // 2. 只有友元类Singleton<DesignPattern>能调用
    DesignPattern() {}

    // 私有析构函数:
    // 1. 禁止外部直接delete DesignPattern对象
    // 2. 程序结束时,局部静态变量instance会自动析构,调用该析构函数(无需手动处理内存泄漏)
    ~DesignPattern() {}
};

5,工厂模式

工厂方法:对应创建流程较为复杂的场景(比如连接池、线程池;隐藏对象真实类型;对象创建时需要有很多参数来决定如何创建;创建对象有复杂的依赖关系)

        主要思路::工厂方法模式通过将具体产品的创建逻辑拆分到对应具体工厂类中,修正了简单工厂模式违反开闭原则的问题,新增产品时只需扩展具体产品类和对应具体工厂类,无需修改原有任何代码,且将产品选择的决策(若有)转移至客户端(或外部配置),不影响核心逻辑。

#include <iostream>
#include <string>

// 产品基类:雷锋
class LeiFeng {
public:
    virtual void Sweep() {
        std::cout << "雷锋扫地" << std::endl;
    }

    virtual ~LeiFeng() {}
};

// 具体产品1:大学生
class Student : public LeiFeng {
public:
    virtual void Sweep() override {
        std::cout << "大学生扫地" << std::endl;
    }
};

// 具体产品2:志愿者
class Volenter : public LeiFeng {
public:
    virtual void Sweep() override {
        std::cout << "志愿者扫地" << std::endl;
    }
};

// 抽象工厂基类:封装产品创建和生命周期管理
class LeiFengFactory {
public:
    LeiFengFactory() : _leiFeng(nullptr) {}

    // 封装核心业务方法
    void DoSweep() {
        if (_leiFeng == nullptr) {
            _leiFeng = CreateLeiFeng();
        }
        _leiFeng->Sweep();
    }

    virtual ~LeiFengFactory() {
        if (_leiFeng != nullptr) {
            delete _leiFeng;
            _leiFeng = nullptr;
        }
    }

protected:
    // 纯虚函数:由子类实现具体产品创建
    virtual LeiFeng* CreateLeiFeng() = 0;

private:
    LeiFeng* _leiFeng;
};

// 具体工厂1:大学生工厂
class StudentFactory : public LeiFengFactory {
protected:
    virtual LeiFeng* CreateLeiFeng() override {
        return new Student();
    }
};

// 具体工厂2:志愿者工厂
class VolenterFactory : public LeiFengFactory {
protected:
    virtual LeiFeng* CreateLeiFeng() override {
        return new Volenter();
    }
};

// 客户端调用
int main() {
    // 创建具体工厂(而非抽象工厂)
    LeiFengFactory* factory = new StudentFactory();
    // 完成业务操作,无需关心产品创建和释放(析构时自动释放产品)
    factory->DoSweep();

    delete factory;
    return 0;
}

6,抽象工厂

抽象工厂是在工厂模式之上,除了创建同类对象,同类对象还有多个相同职责(多个功能接口)

用多继承的方式,本质上是增加功能接口,只需要 new 一个对象就行

        主要思路:定义了一个创建一系列相关或相互依赖的接口,而无需指定它们的具体类(不需要直接写new,具体类的创建被隐藏在具体工厂内部);客户端想要切换产品系列时,只需要更换具体工厂的实例;产品的具体类名被具体工厂的实现分离(客户端不需要知道具体产品的类名,只在具体工厂的内部实现中出现)。

「多个功能接口」是 IUserIDepartment; GetUser() 是接口定义的「功能方法/接口方法」;工厂模式和抽象工厂主要区别是单个和多个功能接口,而接口方法,两种模式都可以定义多个

#include <string>
#include <iostream>
using namespace std;

// ====================== 抽象产品层:定义产品的核心行为规范 ======================
// 用户抽象接口
class IUser {
public:
    virtual void GetUser()=0;     // 获取用户信息
    virtual void InsertUser()=0;  // 插入用户信息
    virtual ~IUser(){}
};

// 部门抽象接口
class IDepartment {
public:
    virtual void GetDepartment()=0;    // 获取部门信息
    virtual void InsertDepartment()=0; // 插入部门信息
    virtual ~IDepartment(){} // 虚析构
};

// ====================== 具体产品层:实现抽象产品定义的行为规范 ======================
// ACCESS 用户:实现IUser接口,适配ACCESS数据库
class CAccessUser : public IUser {
public:
    virtual void GetUser() {
        cout<<"Access GetUser"<<endl;
    }
    virtual void InsertUser() {
        cout<<"Access InsertUser"<<endl;
    }
};

// ACCESS 部门
class CAccessDepartment : public IDepartment {
public:
    virtual void GetDepartment() {
        cout<<"Access GetDepartment"<<endl;
    }
    virtual void InsertDepartment() {
        cout<<"Access InsertDepartment"<<endl;
    }
};

// SQL 用户
class CSqlUser : public IUser {
public:
    virtual void GetUser() {
        cout<<"Sql User"<<endl;
    }
    virtual void InsertUser() {
        cout<<"Sql InsertUser"<<endl;
    }
};

// SQL 部门类
class CSqlDepartment: public IDepartment {
public:
    virtual void GetDepartment() {
        cout<<"sql getDepartment"<<endl;
    }
    virtual void InsertDepartment() {
        cout<<"sql insertdepartment"<<endl;
    }
};

// ========= 抽象工厂层:定义「用户+部门」产品族的创建规范,封装产品调用和资源管理 ==========
// 抽象工厂
class IFactory {
public:
    IFactory() : _user(nullptr), _department(nullptr) {}
    // 封装产品调用逻辑,客户端无需直接操作产品
    void GetUserInfo() {
        if (_user == nullptr) _user = CreateUser();  // 功能接口
        _user->GetUser();  // 接口方法1
    }
    void InsertUserInfo() {
        if (_user == nullptr) _user = CreateUser();
        _user->InsertUser();  // 接口方法2
    }
    void GetDeptInfo() {
        if (_department == nullptr) _department = CreateDepartment();  // 功能接口
        _department->GetDepartment();  // 接口方法1
    }
    void InsertDeptInfo() {
        if (_department == nullptr) _department = CreateDepartment();
        _department->InsertDepartment();  // 接口方法2
    }

    // 析构函数自动释放资源
    virtual ~IFactory() {
        if (_user) delete _user;
        if (_department) delete _department;
    }

protected:
    virtual IUser* CreateUser()=0;
    virtual IDepartment* CreateDepartment()=0;
private:
    IUser* _user;
    IDepartment* _department;
};

// =========== 具体工厂层:实现抽象工厂的创建方法,创建具体产品族 ============
// ACCESS 工厂
class AccessFactory : public IFactory {
protected:
    virtual IUser* CreateUser() {
        return new CAccessUser();
    }
    virtual IDepartment* CreateDepartment() {
        return new CAccessDepartment();
    }
};

// SQL 工厂
class SqlFactory : public IFactory {
protected:
    virtual IUser* CreateUser() {
        return new CSqlUser();
    }
    virtual IDepartment* CreateDepartment() {
        return new CSqlDepartment();
    }
};

// ========== 客户端层:调用工厂方法完成业务操作,无需关注内部实现 ============
int main() {
    IFactory* factory= new SqlFactory();
    factory->GetUserInfo();
    factory->InsertUserInfo();
    factory->GetDeptInfo();
    factory->InsertDeptInfo();
    
    delete factory; // 自动释放内部的_user和_department
    return 0;
}

        下面责任链、装饰器、组合模式的设计原则一样:都是用组合的方式解决问题,面向接口编程,并用接口依赖注入方式。

7,责任链

        稳定点通过抽象的流程解决,让它更稳定;变化点想办法扩展(继承多态 或 组合接口)

        链条的节点是一个个处理对象,消除差异可用接口方法(对节点抽象)。接口的作用是要抽象稳定点,稳定点是链条处理关系(么美好成绩中考成绩。不能处理给下一个对象处理);链表关系用函数来抽象(关注 节点个数 和 处理顺序)。

        主要思路:见定义

#include <iostream>
#include <string>
#include <memory>
using namespace std;

// 【Request/Context】请求上下文对象:存储请求的相关数据
class Request
{
public:
    string m_strContent;  
    int m_nNumber;       
};

// 【抽象处理者(Handler)】定义责任链的核心接口
class Manager
{
protected:
    Manager* m_pSuccessor;  // 【后继者(Successor)】
    string m_strName;      

public:
    Manager(string strName) : m_strName(strName), m_pSuccessor(nullptr)
    {
    }

    virtual ~Manager() = default;

    void SetSuccessor(Manager* pSuccessor)
    {
        m_pSuccessor = pSuccessor;
    }

    // Handler的核心方法,实现「能处理则处理,不能则传递」的统一逻辑
    void HandleRequest(Request* pRequest)
    {
        if (CanHandle(pRequest)) 
        {
            ProcessRequest(pRequest);  
        }
        else if (m_pSuccessor != nullptr) 
        {
            m_pSuccessor->HandleRequest(pRequest);
        }
        else  
        {
            cout << m_strName << ":无后续处理者,该请求【" << pRequest->m_nNumber << "】无法被处理!" << endl;
        }
    }

protected:
    virtual bool CanHandle(Request* pRequest) = 0;

    virtual void ProcessRequest(Request* pRequest) = 0;   //实际处理请求的业务逻辑
};

class CommonManager : public Manager
{
public:
    CommonManager(string strName) : Manager(strName)
    {
    }

protected:
    virtual bool CanHandle(Request* pRequest) override
    {
        // 处理规则:请求编号 0 <= n < 10
        if (pRequest != nullptr && pRequest->m_nNumber >= 0 && pRequest->m_nNumber < 10)
        {
            return true;
        }
        return false;
    }

    virtual void ProcessRequest(Request* pRequest) override
    {
        if (pRequest != nullptr)
        {
            cout << "【ConcreteHandler:" << m_strName << "】处理了" << pRequest->m_nNumber << "个请求" << endl;
        }
    }
};

class MajorDomo : public Manager
{
public:
    MajorDomo(string strName) : Manager(strName)
    {
    }

protected:
    virtual bool CanHandle(Request* pRequest) override
    {
        // 处理规则:请求编号 n >= 10 且 < 30
        if (pRequest != nullptr && pRequest->m_nNumber >= 10 && pRequest->m_nNumber < 30)
        {
            return true;
        }
        return false;
    }

    virtual void ProcessRequest(Request* pRequest) override
    {
        if (pRequest != nullptr)
        {
            cout << "【ConcreteHandler:" << m_strName << "】处理了" << pRequest->m_nNumber << "个请求" << endl;
        }
    }
};

class GeneralManager : public Manager
{
public:
    GeneralManager(string strName) : Manager(strName)
    {
    }

protected:
    virtual bool CanHandle(Request* pRequest) override
    {
        // 处理规则:请求编号 n >= 30
        if (pRequest != nullptr && pRequest->m_nNumber >= 30)
        {
            return true;
        }
        return false;
    }

    virtual void ProcessRequest(Request* pRequest) override
    {
        if (pRequest != nullptr)
        {
            cout << "【ConcreteHandler:" << m_strName << "】处理了" << pRequest->m_nNumber << "个请求" << endl;
        }
    }
};

// 【客户端(Client)】组装责任链并发送请求
int main()
{
    unique_ptr<Manager> pCommonManager = make_unique<CommonManager>("张经理");
    unique_ptr<Manager> pMajorDomo = make_unique<MajorDomo>("李总监");
    unique_ptr<Manager> pGeneralManager = make_unique<GeneralManager>("王总经理");

    //【构建责任链】设置后继者,形成链式结构:张经理 → 李总监 → 王总经理
    pCommonManager->SetSuccessor(pMajorDomo.get());
    pMajorDomo->SetSuccessor(pGeneralManager.get());

    unique_ptr<Request> pRequest = make_unique<Request>();

    // 发送第一个请求:33(由总经理处理)
    pRequest->m_nNumber = 33;
    pCommonManager->HandleRequest(pRequest.get());  //get()从智能指针中提取出原始指针

    // 发送第二个请求:3(由普通经理处理)
    pRequest->m_nNumber = 3;
    pCommonManager->HandleRequest(pRequest.get());

    // 发送第三个请求:15(由总监处理)
    pRequest->m_nNumber = 15;
    pCommonManager->HandleRequest(pRequest.get());

    // 智能指针自动释放内存
    return 0;
}

注意:nginx阶段处理 本质上是责任链模式

8,装饰器

装饰器与责任链不同,顺序是无关的  且  使用组合的方式而非继承(继承耦合度高)

扩展功能:写一个继承方法写一个自己的职责,再在 main 函数加上此方法

      主要思路:向旧的类中添加新代码,一般是为了添加核心职责或主义行为。装饰模式就是要把添加的附加功能分别放在单独的类中,并让这个类包含要装饰的对象,当需要执行时,客户端就可以有选择、按顺序地使用装饰功能包装的对象。

基础结构:

#include <string>
#include <iostream>

using namespace std;

// 基类
class Person
{
private:
    string m_strName;

public:
    Person(string strName) : m_strName(strName)
    {
    }

    Person()
    {
    }

    virtual void Show()
    {
        cout << "装扮的是:" << m_strName << endl;
    }

    virtual ~Person()
    {
    }
};


// 装饰类
class Finery : public Person
{
protected:
    Person* m_component = nullptr;

public:
    void Decorate(Person* component)
    {
        m_component = component;
    }

    virtual void Show() override
    {
        if (m_component != nullptr)
        {
            m_component->Show();
        }
    }

    virtual ~Finery() override
    {
    }
};

//具体装饰1
class TShirts : public Finery
{
public:
    virtual void Show() override
    {
        cout << "T Shirts" << endl;
        Finery::Show();
    }
};

//具体装饰2
class BigTrouser : public Finery
{
public:
    virtual void Show() override
    {
        cout << "Big Trouser" << endl;
        Finery::Show();
    }
};

int main()
{
    Person* p = new Person("小李");
    BigTrouser* bt = new BigTrouser();
    TShirts* ts = new TShirts();

    bt->Decorate(p);
    ts->Decorate(bt);

    ts->Show();

    delete ts;
    delete bt;
    delete p;

    return 0;
}

项目案例:

#include <iostream>
using namespace std;
// 普通员工有销售奖金,累计奖金,部门经理除此之外还有团队奖金;后面可能会添加环比增长奖金,同时可能产生不同的奖金组合;
// 销售奖金 = 当月销售额 * 4%
// 累计奖金 = 总的回款额 * 0.2%
// 部门奖金 = 团队销售额 * 1%
// 环比奖金 = (当月销售额-上月销售额) * 1%
// 销售后面的参数可能会调整

// 【Context】上下文对象:传递计算所需的参数
class Context {
public:
    bool isMgr;
    double monthSale;
    double totalReturn;
    double groupSale;
    double lastMonthSale;
};

// 【Component】抽象组件:定义统一的奖金计算接口
class CalcBonus {    
public:
    CalcBonus(CalcBonus *c = nullptr) : cc(c) {}
    virtual double Calc(Context &ctx) = 0;
    virtual ~CalcBonus() = default;

protected:
    CalcBonus* cc;
};

// 【ConcreteComponent】具体组件:基础奖金(基本工资)
class BaseBonus : public CalcBonus {
public:
    double Calc(Context &ctx) override {
        return 3000.0;
    }
};

// 【Decorator】抽象装饰器:持有组件引用,实现统一接口
class BonusDecorator : public CalcBonus {
public:
    BonusDecorator(CalcBonus *c) : CalcBonus(c) {}
    double Calc(Context &ctx) override {
        return cc->Calc(ctx);
    }
};

// 【ConcreteDecorator】具体装饰器:月度销售奖金
class MonthBonus : public BonusDecorator {
public:
    MonthBonus(CalcBonus *c) : BonusDecorator(c) {}
    double Calc(Context &ctx) override {
        double mbonus = ctx.monthSale * 0.04;
        return mbonus + cc->Calc(ctx);
    }
};

// 【ConcreteDecorator】具体装饰器:累计回款奖金
class SumBonus : public BonusDecorator {
public:
    SumBonus(CalcBonus *c) : BonusDecorator(c) {}
    double Calc(Context &ctx) override {
        double sbonus = ctx.totalReturn * 0.002;
        return sbonus + cc->Calc(ctx);
    }
};

// 【ConcreteDecorator】具体装饰器:团队销售奖金
class GroupBonus : public BonusDecorator {
public:
    GroupBonus(CalcBonus *c) : BonusDecorator(c) {}
    double Calc(Context &ctx) override {
        if (!ctx.isMgr) return cc->Calc(ctx);
        double gbonus = ctx.groupSale * 0.01;
        return gbonus + cc->Calc(ctx);
    }
};

// 【ConcreteDecorator】具体装饰器:环比增长奖金
class CycleBonus : public BonusDecorator {
public:
    CycleBonus(CalcBonus *c) : BonusDecorator(c) {}
    double Calc(Context &ctx) override {
        double delta = ctx.monthSale - ctx.lastMonthSale;
        double cbonus = delta > 0 ? delta * 0.01 : 0;
        return cbonus + cc->Calc(ctx);
    }
};

int main() {
    // 普通员工:基础 + 月度 + 累计
    Context empCtx{false, 50000, 200000, 0, 45000};
    CalcBonus *empBonus = new SumBonus(new MonthBonus(new BaseBonus()));
    cout << "普通员工总奖金:" << empBonus->Calc(empCtx) << endl;

    // 部门经理:基础 + 月度 + 累计 + 团队 + 环比
    Context mgrCtx{true, 80000, 500000, 300000, 70000};
    CalcBonus *mgrBonus = new CycleBonus(new GroupBonus(new SumBonus(new MonthBonus(new BaseBonus()))));
    cout << "部门经理总奖金:" << mgrBonus->Calc(mgrCtx) << endl;

    delete empBonus;
    delete mgrBonus;
    return 0;
}

9,组合模式

        主要思路:整体和部分可以被一致对待(如 WORD 中复制一个文字、一段文字、一篇文章都是一样的操作)

#include <iostream>
#include <string>
#include <vector>
using namespace std;

// 抽象组件:定义统一接口
class Component
{
public:
    string m_strName;
    Component (string strName) : m_strName (strName) {}
    // 虚函数 + 默认空实现,叶子节点可直接继承
    virtual void Add (Component* com) {}
    virtual void Remove (Component* com) {}
    virtual Component* GetChild (int index) { return nullptr; }
    virtual void Operation (int nDepth) = 0;
    
    virtual ~Component () {}
};

// 叶子节点:无子节点,仅实现自身操作
class Leaf : public Component
{
public:
    Leaf (string strName) : Component (strName) {}
    void Operation (int nDepth) override
    {
        string strTemp;
        for (int i = 0; i < nDepth; i++) { 
            strTemp += "-";
        }
        strTemp += m_strName;
        cout << strTemp << endl;
    }
};

// 组合节点:持有子节点集合,实现增删和递归操作
class Composite : public Component
{
private:
    vector<Component*> m_children;
public:
    Composite (string strName) : Component (strName) {}

    void Add (Component* com) override
    {
        m_children.push_back (com);
    }

    void Remove (Component* com) override
    {
        for (auto iter = m_children.begin (); iter != m_children.end (); ++iter)
        {
            if (*iter == com) 
            {
                m_children.erase(iter);
                break;
            }
        }
    }

    Component* GetChild (int index) override
    {
        if (index >= 0 && index < m_children.size ()) {
            return m_children [index];
        }
        return nullptr;
    }

    void Operation (int nDepth) override
    {
        // 先执行自身操作
        string strTemp;
        for (int i = 0; i < nDepth; i++) { 
            strTemp += "-";
        }
        strTemp += m_strName;
        cout << strTemp << endl;
        // 递归执行所有子节点操作
        for (auto child : m_children)
        {
            child->Operation (nDepth + 2);
        }
    }

    ~Composite () override
    {
        // 递归释放子节点,避免内存泄漏
        for (auto child : m_children) {
            delete child;
        }
    }
};

// 客户端代码
int main ()
{
    // 创建根组合节点
    Composite* root = new Composite ("小王");
    // 添加叶子节点
    root->Add (new Leaf ("小李"));
    root->Add (new Leaf ("小赵"));
    // 创建子组合节点并添加叶子
    Composite* subComposite = new Composite ("小小五");
    subComposite->Add (new Leaf ("大三"));
    root->Add (subComposite);

    // 统一调用 Operation,无需区分叶子和组合
    root->Operation (1);  // 1为nDepth
    
    // 测试Remove方法
    Component* zhao = root->GetChild(1); // 获取小赵节点
    root->Remove(zhao); // 删除小赵节点
    Component* daSan = subComposite->GetChild(0); // 大三是subComposite的第1个子节点,索引0
    subComposite->Remove(daSan); // 通过直接父节点subComposite删除大三

    root->Operation (1);  // 1为nDepth
   
    delete root;  // 释放根节点(自动递归释放所有子节点)
    return 0;
}

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐