外观、装饰和组合模式(结构型设计模式)的 C++ 代码示例模板。
2023-12-20 13:46:13
前言
外观、装饰和组合模式(结构型设计模式)的 C++ 代码示例模板。
代码仓库
外观模式(Facade)
结构
- 子系统类(多个)(被管理者)
- 外观类(管理者)
- 外观类 封装 子系统对象
- 外观类的方案方法 调用子系统对象的方法 搭配成不同方案 (不同对象、方法(内容)和时序/步骤等)
- 客户端只知道外观类,不知道子系统类
代码
#include <iostream>
using std::cout;
using std::endl;
// 子系统类(多个)(被管理者)
// 子系统 A 类
class SubsystemA
{
public:
void func_A()
{
cout << "func_A()" << endl;
}
};
// 子系统 B 类
class SubsystemB
{
public:
void func_B()
{
cout << "func_B()" << endl;
}
};
// 外观类(管理者)
class Facade
{
public:
Facade() : subsystem_A(), subsystem_B() {} // 子系统类的 默认构造方法初始化 子系统对象
// 外观类的方案方法 调用子系统对象的方法 搭配成不同方案(不同对象、方法(内容)和时序/步骤等)
// 方案1
void option1()
{
subsystem_A.func_A();
subsystem_B.func_B();
}
// 方案2
void option2()
{
subsystem_B.func_B();
subsystem_A.func_A();
}
// 方案n...
private:
// 外观类 封装 子系统对象
SubsystemA subsystem_A;
SubsystemB subsystem_B;
};
// 客户端
int main()
{
// 客户端只知道外观类,不知道子系统类
Facade facade;
facade.option1(); // 使用方案1
facade.option2(); // 使用方案2
return 0;
}
/*
输出:
func_A()
func_B()
func_B()
func_A()
*/
装饰模式(Decorator)
结构
- 抽象组件类
- 具体组件类(被装饰者)
- 抽象装饰类
- 具体装饰类(装饰者)
- 抽象装饰类 继承 抽象组件类
- 抽象装饰类 封装 抽象组件指针(实际上会指向一个具体组件对象)(装饰者包装被装饰者)
- 抽象装饰类 重写 抽象组件类的方法
- 形式上 调用 装饰类的方法
- 实际上 调用 抽象组件指针/具体组件对象的方法(原本内容) + 装饰类的额外内容(装饰内容) (重点理解)
- 具体装饰类 重写 抽象组件类的方法
- 形式上 调用 装饰类的方法
- 实际上 调用 抽象组件指针/具体组件对象的方法(原本内容) + 装饰类的额外内容(装饰内容) (重点理解)
- 注意浅拷贝和深拷贝问题:相同组件不同装饰,需要浅拷贝
- 注意同一组件不同装饰的重复析构问题
代码
#include <iostream>
using std::cout;
using std::endl;
// 抽象组件类
class AbstractComponent
{
public:
virtual ~AbstractComponent() = default;
virtual void func() = 0;
};
// 具体组件类(被装饰者)
class ConcreteComponent : public AbstractComponent
{
public:
void func() override
{
cout << "component" << endl;
}
};
// 抽象装饰类
// 抽象装饰类 继承 抽象组件类
class AbstractDecorator : public AbstractComponent
{
public:
// 注意浅拷贝和深拷贝问题:相同组件不同组件,需要浅拷贝
AbstractDecorator(AbstractComponent *abstract_component) : abstract_component(abstract_component) {}
virtual ~AbstractDecorator() override
{
delete this->abstract_component;
}
// 抽象装饰类 重写 抽象组件类的方法
// 形式上 调用 装饰类的方法
// 实际上 调用 抽象组件指针/具体组件对象的方法(原本内容) + 装饰类的额外内容(装饰内容)(重点理解)
void func() override
{
if (this->abstract_component != nullptr)
{
this->abstract_component->func();
}
}
private:
// 抽象装饰类 封装 抽象组件指针(实际上会指向一个具体组件对象)(装饰者包装被装饰者)
AbstractComponent *abstract_component;
};
// 具体装饰 A 类
class ConcreteDecoratorA : public AbstractDecorator
{
public:
ConcreteDecoratorA(AbstractComponent *abstract_component) : AbstractDecorator(abstract_component) {}
// 具体装饰类 重写 抽象组件类的方法
void func() override // 形式上 调用 装饰类的方法
{
AbstractDecorator::func(); // 实际上 调用 抽象组件指针/具体组件对象的方法(原本内容)
cout << "ConcreteDecoratorA" << endl; // + 装饰类的额外内容(装饰内容)(重点理解)
}
};
// 具体装饰 B 类
class ConcreteDecoratorB : public AbstractDecorator
{
public:
ConcreteDecoratorB(AbstractComponent *abstract_component) : AbstractDecorator(abstract_component) {}
// 具体装饰类 重写 抽象组件类的方法
void func() override // 形式上 调用 装饰类的方法
{
AbstractDecorator::func(); // 实际上 调用 抽象组件指针/具体组件对象的方法(原本内容)
cout << "ConcreteDecoratorB" << endl; // + 装饰类的额外内容(装饰内容)(重点理解)
}
};
// 客户端
int main()
{
// 注意同一组件不同装饰的重复析构问题
// AbstractComponent *abstract_component = new ConcreteComponent(); // 抽象组件指针/具体组件对象
// // 抽象组件指针/具体装饰 A 对象装饰组件
// AbstractComponent *concrete_decorator_A = new ConcreteDecoratorA(abstract_component);
// concrete_decorator_A->func(); // 形式上 调用 装饰类的方法
// AbstractComponent *concrete_decorator_B = new ConcreteDecoratorB(abstract_component);
// concrete_decorator_B->func();
// delete concrete_decorator_B; // 第一次 delete abstract_component
// delete concrete_decorator_A; // 第二次 delete abstract_component
// delete abstract_component; // 第三次 delete abstract_component
// 解决1:使用智能指针,shared_ptr<>
// 解决2:手动实现引用计数机制
// 解决3:程序结束自动释放全部
// 解决4:使用相同组件的不同副本
// 解决5:使用不同组件
// 解决n...
// 使用解决5
AbstractComponent *abstract_component_a = new ConcreteComponent(); // 抽象组件指针/具体组件对象
// 抽象组件指针/具体装饰 A 对象装饰组件
AbstractComponent *concrete_decorator_A = new ConcreteDecoratorA(abstract_component_a);
concrete_decorator_A->func(); // 形式上 调用 装饰类的方法
delete concrete_decorator_A; // 第一次 delete abstract_component
// delete abstract_component_a; // 第二次 delete abstract_component
AbstractComponent *abstract_component_b = new ConcreteComponent();
AbstractComponent *concrete_decorator_B = new ConcreteDecoratorB(abstract_component_b);
concrete_decorator_B->func();
delete concrete_decorator_B;
return 0;
}
组合模式(Composite)
结构
- 组件类
- 树叶类(树的叶节点)
- 树枝类(树的非叶节点)
- 树叶类 继承 组件类,重写 虚方法
- 树枝类 继承 组件类,封装 组件类的集合(实际上包含零个或多个树叶对象或树枝对象),重写 虚方法
- 客户端 以相同的方式处理/一致地使用 简单和复杂元素/单个和组合对象
类型
- 透明方式:组件类有管理子对象的方法(添加组件方法和删除组件方法等),树枝类和叶子类的行为一致;但叶子类继承和实现该些方法没有意义,违反接口隔离原则(ISP)
- 安全方式:组件类没有管理子对象的方法,树枝类有管理子对象的方法
代码(安全方式)
// 安全方式:组件类没有管理子对象的方法,树枝类有管理子对象的方法
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
// 组件类
class Component
{
public:
virtual ~Component() {}
virtual void func() = 0;
};
// 树叶类(树的叶节点)
// 树叶类 继承 组件类,重写 虚方法
class Leaf : public Component
{
public:
Leaf(int value) : value(value) {}
void func() override
{
cout << "Leaf: " << this->value << endl;
return;
}
private:
int value;
};
// 树枝类(树的非叶节点)
// 树枝类 继承 组件类,封装 组件类的集合(实际上包含零个或多个树叶对象或树枝对象),重写 虚方法
class Branch : public Component
{
public:
Branch() : component_vec() {} // vector<> 的 默认构造方法初始化 属性
~Branch()
{
for (Component *component : this->component_vec)
{
delete component;
}
}
void add(Component *component)
{
this->component_vec.push_back(component);
}
void func() override
{
cout << "Branch: " << endl;
for (Component *component : this->component_vec)
{
component->func();
}
}
private:
vector<Component *> component_vec;
};
// 客户端
int main()
{
// 树叶
Leaf *leaf_1 = new Leaf(10);
Leaf *leaf_2 = new Leaf(20);
Leaf *leaf_3 = new Leaf(30);
// 树枝
Branch *branch_1 = new Branch();
branch_1->add(leaf_1);
branch_1->add(leaf_2);
// 树枝/根
Branch *branch_2 = new Branch();
branch_2->add(leaf_3);
branch_2->add(branch_1);
// 客户端 以相同的方式处理/一致地使用 简单和复杂元素/单个和组合对象
leaf_2->func();
cout << endl;
branch_2->func();
delete branch_2; // 会自动递归 delete branch_1、leaf_2、leaf_1 和 leaf_3
return 0;
}
/*
Leaf: 20
Branch:
Leaf: 30
Branch:
Leaf: 10
Leaf: 20
*/
总结
外观、装饰和组合模式(结构型设计模式)的 C++ 代码示例模板。
参考资料
作者的话
- 感谢参考资料的作者/博主
- 作者:夜悊
- 版权所有,转载请注明出处,谢谢~
- 如果文章对你有帮助,请点个赞或加个粉丝吧,你的支持就是作者的动力~
- 文章在描述时有疑惑的地方,请留言,定会一一耐心讨论、解答
- 文章在认识上有错误的地方, 敬请批评指正
- 望读者们都能有所收获
文章来源:https://blog.csdn.net/m0_62083249/article/details/135093683
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!