Linux c++学习 1.4.设计模式

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,具体类的创建被隐藏在具体工厂内部);客户端想要切换产品系列时,只需要更换具体工厂的实例;产品的具体类名被具体工厂的实现分离(客户端不需要知道具体产品的类名,只在具体工厂的内部实现中出现)。

「多个功能接口」是 IUser 和 IDepartment; 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;
}
更多推荐






所有评论(0)