工厂模式和装饰器模式在程序设计中的体现

工厂模式

Step 1: 更新基类

在基类中添加保护方法,这些方法可以被子类调用以实现公共的逻辑。

model.h

#ifndef MODEL_H
#define MODEL_Hclass Model {
public:virtual ~Model() {}void init() {preInit();doInit();postInit();}void process() {preProcess();doProcess();postProcess();}void destroy() {preDestroy();doDestroy();postDestroy();}protected:virtual void doInit() = 0;virtual void doProcess() = 0;virtual void doDestroy() = 0;virtual void preInit() {// 公共的初始化前逻辑}virtual void postInit() {// 公共的初始化后逻辑}virtual void preProcess() {// 公共的处理前逻辑}virtual void postProcess() {// 公共的处理后逻辑}virtual void preDestroy() {// 公共的销毁前逻辑}virtual void postDestroy() {// 公共的销毁后逻辑}
};#endif // MODEL_H

Step 2: 更新具体模型

在具体模型中实现纯虚函数,并在需要的地方调用基类的保护方法。

ModelA.h
#ifndef MODELA_H
#define MODELA_H#include "model.h"class ModelA : public Model {
protected:void doInit() override;void doProcess() override;void doDestroy() override;
};#endif // MODELA_H
ModelA.cpp
#include "ModelA.h"
#include <iostream>void ModelA::doInit() {std::cout << "ModelA specific initialization." << std::endl;
}void ModelA::doProcess() {std::cout << "ModelA specific processing." << std::endl;
}void ModelA::doDestroy() {std::cout << "ModelA specific destruction." << std::endl;
}

Step 3: 更新工厂和主程序

工厂和主程序的代码无需改变,因为它们依然通过基类接口与模型进行交互。

ModelFactory.h
#ifndef MODELFACTORY_H
#define MODELFACTORY_H#include "model.h"
#include <string>
#include <memory>class ModelFactory {
public:static std::unique_ptr<Model> createModel(const std::string& modelName);
};#endif // MODELFACTORY_H
ModelFactory.cpp
#include "ModelFactory.h"
#include "ModelA.h"
// #include "ModelB.h" // 包含其他模型头文件std::unique_ptr<Model> ModelFactory::createModel(const std::string& modelName) {if (modelName == "ModelA") {return std::make_unique<ModelA>();}// else if (modelName == "ModelB") {//     return std::make_unique<ModelB>();// }// 可以添加更多的模型创建逻辑return nullptr;
}
main.cpp
#include <iostream>
#include "ModelFactory.h"int main() {std::unique_ptr<Model> model = ModelFactory::createModel("ModelA");if (model) {model->init();model->process();model->destroy();} else {std::cerr << "Model creation failed." << std::endl;}return 0;
}

装饰器模式:

Step 1: 定义基类

定义一个基类 Model,其中包含纯虚函数 doInit()doProcess()doDestroy(),这些函数将由具体模型类实现。

model.h
#ifndef MODEL_H
#define MODEL_Hclass Model {
public:virtual ~Model() {}virtual void init() = 0;virtual void process() = 0;virtual void destroy() = 0;
};#endif // MODEL_H

Step 2: 定义具体模型

具体模型继承自 Model 并实现必要的方法。

ModelA.h
#ifndef MODELA_H
#define MODELA_H#include "model.h"class ModelA : public Model {
public:void init() override;void process() override;void destroy() override;
};#endif // MODELA_H
ModelA.cpp
#include "ModelA.h"
#include <iostream>void ModelA::init() {std::cout << "ModelA specific initialization." << std::endl;
}void ModelA::process() {std::cout << "ModelA specific processing." << std::endl;
}void ModelA::destroy() {std::cout << "ModelA specific destruction." << std::endl;
}

Step 3: 定义装饰器

定义一个装饰器基类 ModelDecorator,它继承自 Model 并包含一个 Model 对象的引用。这个装饰器基类将实现 Model 接口,并委托调用给被装饰的模型对象。

ModelDecorator.h
#ifndef MODELDECORATOR_H
#define MODELDECORATOR_H#include "model.h"
#include <memory>class ModelDecorator : public Model {
public:ModelDecorator(std::shared_ptr<Model> model) : model_(model) {}void init() override {model_->init();}void process() override {model_->process();}void destroy() override {model_->destroy();}protected:std::shared_ptr<Model> model_;
};#endif // MODELDECORATOR_H

Step 4: 定义具体装饰器

具体装饰器实现共享的逻辑,例如在初始化前后执行一些操作。

LoggingDecorator.h
#ifndef LOGGINGDECORATOR_H
#define LOGGINGDECORATOR_H#include "ModelDecorator.h"
#include <iostream>class LoggingDecorator : public ModelDecorator {
public:LoggingDecorator(std::shared_ptr<Model> model) : ModelDecorator(model) {}void init() override {preInit();ModelDecorator::init();postInit();}void process() override {preProcess();ModelDecorator::process();postProcess();}void destroy() override {preDestroy();ModelDecorator::destroy();postDestroy();}protected:void preInit() {std::cout << "Common pre-initialization logic." << std::endl;}void postInit() {std::cout << "Common post-initialization logic." << std::endl;}void preProcess() {std::cout << "Common pre-processing logic." << std::endl;}void postProcess() {std::cout << "Common post-processing logic." << std::endl;}void preDestroy() {std::cout << "Common pre-destruction logic." << std::endl;}void postDestroy() {std::cout << "Common post-destruction logic." << std::endl;}
};#endif // LOGGINGDECORATOR_H

Step 5: 使用模型和装饰器

在主程序中组合模型和装饰器。

main.cpp
#include <iostream>
#include <memory>
#include "ModelA.h"
#include "LoggingDecorator.h"int main() {std::shared_ptr<Model> model = std::make_shared<ModelA>();std::shared_ptr<Model> decoratedModel = std::make_shared<LoggingDecorator>(model);if (decoratedModel) {decoratedModel->init();decoratedModel->process();decoratedModel->destroy();} else {std::cerr << "Model creation failed." << std::endl;}return 0;
}

解释虚函数 doInit(), doProcess(), doDestroy()

在基类中定义纯虚函数 doInit(), doProcess(), doDestroy() 的原因是:

  1. 强制子类实现:这些纯虚函数确保所有具体模型必须实现这些方法,定义了模型的基本行为接口。
  2. 实现分离:通过将公共逻辑和具体实现分离,基类可以实现公共的逻辑框架,而具体模型实现细节。
  3. 可扩展性:子类可以提供各自的具体实现,而无需修改基类,使系统具有良好的扩展性和灵活性。

通过使用装饰器模式,我们将公共逻辑封装在装饰器中,同时保留了具体模型的灵活性和可扩展性。这种设计既满足了代码复用的需求,又保持了系统的模块化和可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/17158.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C/C++】观察者模式

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

牛客周赛44 F小红的基环树删边

原题链接&#xff1a;F-小红的基环树删边 题目大意&#xff1a;给一个基环树&#xff0c;一个n个点&#xff0c;n条边。若是删除第i边&#xff0c;从1到n的最短距离是多少&#xff1f; 思路&#xff1a;因为是基环树&#xff0c;那么从1到n最多就只有二条路径&#xff0c;那么…

香橙派 AIpro开发体验:使用YOLOV8对USB摄像头画面进行目标检测

香橙派 AIpro开发体验&#xff1a;使用YOLOV8对USB摄像头画面进行目标检测 前言一、香橙派AIpro硬件准备二、连接香橙派AIpro1. 通过网线连接路由器和香橙派AIpro2. 通过wifi连接香橙派AIpro3. 使用vscode 通过ssh连接香橙派AIpro 三、USB摄像头测试1. 配置ipynb远程开发环境1.…

【程序填空题】日期比较(运算符重载)

题目描述 定义一个日期类CDate&#xff0c;包含属性&#xff1a;年、月、日&#xff0c;都是整数。 构造函数含单个参数&#xff0c;参数是八位整数&#xff0c;默认值为0&#xff0c;实现整数转为日期类型&#xff0c;例如参数为20170612&#xff0c;转为year2017, month6, …

Python实现批量删除Word文档内容中的“指定”内容(5)

前言 本文是该专栏的第5篇,后面会持续分享Python办公自动化干货知识,记得关注。 如果说,有这样的一个需求——有一批废弃词,需要你通过python,对目标word文档中包含这些废弃词的目标内容,进行批量删除。接到这样的需求,第一时间你会想到需要怎么去解决呢? 而本文,笔…

Python实现批量修改Word文档内容的字体大小(6)

前言 本文是该专栏的第6篇,后面会持续分享Python办公自动化干货知识,记得关注。 在本专栏上一篇文章《Python实现批量删除Word文档内容中的“指定”内容(5)》中,笔者有详细介绍通过python删除word文档内容中的“指定内容”。 而本文,在上一篇文章的思路基础上,再实现一…

Mybatis多表查询,报错:Column ‘id‘ in field list is ambiguous

错误原因&#xff1a; Mybatis 多表查询时&#xff0c;多个表有相同名字的字段&#xff0c;比如 id&#xff0c;名字重复&#xff0c;没有指定对应的表名。 有两个地方需要注意&#xff1a;(1)将其中一个重复字段的 Mybatis的 column 修改为其他的名字。(2)字段加上对应的表名…

Java 8 Lambda 表达式:新手入门指南

随着Java 8的发布&#xff0c;Lambda 表达式成为了Java编程中一个不可或缺的特性。Lambda 表达式允许我们以更简洁、更直观的方式表示函数式接口的实例。本文将引导新手如何开始使用Java 8的Lambda表达式。 1. 什么是Lambda表达式&#xff1f; Lambda 表达式是一个匿名函数&…

AI重塑了我的工作流

阅读内容 Inhai: Agentic Workflow&#xff1a;AI 重塑了我的工作流 4 种主要的 Agentic Workflow 设计模式 Reflection&#xff08;反思&#xff09;&#xff1a;让 Agent 审视和修正自己生成的输出。 举例&#xff1a;如果有两个 Agent&#xff1a;一个负责 Coding&#…

损失函数篇 | YOLOv8更换损失函数之Inner-IoU | 通过辅助边界框计算IoU损失

前言:Hello大家好,我是小哥谈。损失函数是机器学习中用来衡量模型预测值与真实值之间差异的函数。在训练模型时,我们希望通过不断调整模型参数,使得损失函数的值最小化,从而使得模型的预测值更加接近真实值。为弥补现有IoU损失函数在不同的检测任务中的泛化能力较弱且收敛…

unity制作app(9)--拍照 相册 上传照片

1.传输照片&#xff08;任何较大的数据&#xff09;都需要扩展服务器的内存空间。 2.还需要base64编码 2.1客户端发送位置的编码 2.2服务器接收部分的代码

数据链路层 + NAT技术

数据链路层&#xff1a;负责设备之间的数据帧的传送和识别。 一、以太网 以太网的帧格式 如何分离报头和有效数据&#xff1f; 报头是固定长度的 如何将数据交给上层协议&#xff1f; 通过类型&#xff0c;如果是0800&#xff0c;则交给IP协议&#xff0c;如果是0806&#xf…

Vue中使用Axios

安装Axios&#xff1a; 首先确保已经安装了Axios。你可以使用npm或者yarn进行安装&#xff0c;如下所示&#xff1a; pm install axios 导入Axios&#xff1a; 在需要发送HTTP请求的组件中&#xff0c;使用import语句导入Axios库。 import axios from axios; 发送HTTP请求&…

前端HTML5从入门到精通面试题及参考答案(2万字长文)

目录 描述HTML5与HTML4的主要区别是什么? HTML5为什么不基于SGML? HTML5的DOCTYPE声明是什么?

力扣爆刷第145天之图论五连刷(dfs和bfs)

力扣爆刷第145天之图论五连刷&#xff08;dfs和bfs&#xff09; 文章目录 力扣爆刷第145天之图论五连刷&#xff08;dfs和bfs&#xff09;总结一、797. 所有可能的路径二、200. 岛屿数量三、695. 岛屿的最大面积四、1020. 飞地的数量五、130. 被围绕的区域 总结 dfs是一条路走…

Debug - nacos配置 第二弹

好的 又是一个蠢蠢的 nacos 配置上出现的问题 在使用 nacos 进行 配置共享时 报错 Description: Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver c…

5.30边缘智能开发工具链全解析 | 2024高通边缘智能创新应用大赛公开课

2024高通边缘智能创新应用大赛系列公开课迎来精彩续篇&#xff01;本期课程将由阿加犀智能科技技术总监秦朝&#xff0c;为大家带来一场关于边缘智能方案与创新应用的深度分享。 作为本次大赛的联合主办方&#xff0c;阿加犀为比赛设备提供强大的软件支持。 各位参赛者将上手…

谷歌忙于手动删除自己搜索引擎中奇怪的人工智能答案

该公司确认正在“迅速采取行动”消除人工智能工具的一些奇怪反应。 社交媒体上充斥着谷歌新的人工智能概述产品的例子&#xff0c;这些产品说了一些奇怪的话&#xff0c;从告诉用户在披萨上涂胶水到建议他们吃石头。混乱的推出意味着&#xff0c;随着各种表情包的发布&#xf…

Android Gradle文件 一次通关

前言 Android的Gradle是每个项目一定包含的文件&#xff0c;用来定义构建配置的脚本文件&#xff0c;通常包括两个主要文件&#xff1a;build.gradle&#xff08;项目级别&#xff09;和build.gradle&#xff08;模块级别&#xff09;。 项目级别的 build.gradle 文件 项目级…

【Typescript】通过变量的值即可获取变量的类型【typeof 变量】

注意&#xff1a;只要变量的类型准确,则typeof获取变量的类型就不会错 enum Test {a "a0",b "b0" }// 这里的a是一个变量的值 let a: Test.a "a0" as Test.a// 这里的typeof a是一个类型【Test.a】 let x: typeof a Test.a