【组件协作】模板方法

文章目录

  • 模板方法
    • 总体划分
    • 重构
    • 组件协作模式——模板方法
      • 动机
      • 代码——做法一
      • 代码——做法二
      • 对比
      • 定义
      • 缺点
      • 总结
    • 其他

模板方法

总体划分

设计模式的总体分类:
目的:

  • 创建型:解决对象创建的工作
  • 结构型:对象在需求变化对结构的冲击
  • 行为型: 多个类交互的责任的划分

范围:

  • 类模式处理类与子类的静态关系
  • 对象模式处理对象间的动态关系

从封装变化角度:

  • 组件协作类:协作问题
    • Template Method
    • Strategy
    • Observer/Event
  • 单一职责:类与类的责任划分问题
    • Decorator
    • Bridge
  • 对象创建:对象创建的依赖关系
    • Factory Method
    • Abstract Factory
    • Prototype
    • Builder
  • 对象性能:对象性能的优化问题
    • Singleton
    • Flyweight
  • 接口隔离
    • Facade
    • Proxy
    • Mediator
    • Adapter
  • 状态变化
    • Memento
    • State
  • 数据结构
    • Composite
    • Iterator
    • Chain of Responsibility
  • 行为变化
    • Command
    • visitor
  • 领域问题
    • Interpreter

重构

书籍推荐:

  • 《重构——改善既有代码的设计》
  • 《重构与模式》

设计模式的应用并非一蹴而就, 而是不断的重构, 其中的关键技法:

  • 静态->动态
  • 早绑定->晚绑定
  • 继承->组合
  • 编译时依赖->运行时依赖
  • 紧耦->松耦合

组件协作模式——模板方法

现代软件专业分工之后的第一个结果就是:框架和应用程序
组件协作模式通过晚绑定, 来实现框架与应用之间的松耦合

典型代表:

  • Template Method
  • Strategy
  • Observer/Event

当然, 并不是说其他的设计模式与组件协作无关, 而是想表达:这些模式体现明显

动机

在软件构建中, 常常有稳定的整体框架, 但各个子不走有很多改变的需求, 或者由于固有的原因
比如框架和应用之间的关系, 而无法和任务的整体结构同时实现

那么, 如何在确定稳定操作结构的前提下, 来灵活应对个子步骤的变化或者晚期实现需求

代码——做法一

库:
lib.cpp

class Library
{
public:void Step1(){// code}void Step3(){// code}void Step5(){// code}
};

应用层:

class Application
{
public:bool Step2(){// code}void Step4(){// code}
}// 模拟的业务逻辑
int main()
{Library lib;Application app;lib.Step1();if (app.Step2()){lib.Step3();}for (size_t i = 0; i < 4; ++ i){app.Step4();}lib.Step5();return 0;
}

代码——做法二

库:
lib.cpp

class Library
{
public:// 稳定 template methodvoid Run(){Step1();if (Step2()){// 支持变化->虚函数多态调用Step3();}for (size_t i = 0; i < 4; ++ i){// 支持变化->虚函数多态调用Step4();}Step5();}virtual ~Library(){// code}protected:virtual void Step1(){// 稳定// code}virtual void Step3(){// 稳定// code}virtual void Step5(){// 稳定// code}virtual bool Step2() = 0;   // 变化virtual void Step4() = 0;   // 变化
}

应用程序开发:
main.cpp

class Application : public Library
{
protected:virtual bool Step2(){// 子类的重写实现}virtual void Step4(){// 子类的重写实现}
};int main()
{Library *lib = new Application();lib->Run();delete lib;return 0;
}

对比

对于写法一
业务有五个步骤:
lib库完成1, 3, 5
业务开发人员完成:2, 4和程序主体

对于做法二:
lib库仍然完成1, 3, 5
但是lib库开发多完成了一个程序主流程

而Application开发人员完成:2, 4

调用关系:
方法一:Application开发人员调用库函数
方法二:Application开发人员调用程序主体(虚函数)

那么可以看出:
方法一:早绑定的做法, 为什么是早绑定

  1. 因为库写的早, Appcation的开发晚, 一个晚的东西调用早的东西就是早绑定

早绑定一直是面向过程时期的做法, 但是在面向对象这, 就有了晚绑定
虽然lib仍然是写的早, Application开发仍然是晚
但是lib反过来调用了Application, 也就是早的东西调用晚东西, 这个就叫晚绑定

因此就可以引出模板方法的定义:

定义

定义一个操作中的算法的骨架(稳定, 上面demo的Run方法), 而将一些步骤延迟(变化)到子类中。
Template Method使得子类可以不改变(复用)一个算法的结构即可实现重定义(override重写)该算法的某些步骤

缺点

这个做法的Run必须得是稳定的, 因此如果Run不稳定, 则此设计模式不适用
这也是Template Method定义中提到的:一个操作中算法的骨架

那么还有一个有趣的点:
假设Step2和Step4都是稳定, 那么Template Method就没必要使用了, 反正都是稳定的
根本原因是因为设计模式的核心是在变化和稳定之间寻找分界点, 来分离和管理变化
将变化关在一个笼子里, 任由其在笼子里蹦跶, 但是不影响整个系统

总结

那么回过头来思考一下, 为什么要把程序的主体流程放在lib库里完成?
答案呼之欲出, 因为要稳定

但是这样也有弊端:
用方法一:业务开发人员不得不完成主流程, 其业务水平会得到很大的提升, 因为你不完成, 整个Application就无法实现
方法二:核心在父类里, 而业务开发人员不用写主流程, 甚至只要override几个虚函数就可以了

因此如果你是方法二的业务开发人员, 你会有一种只见树木不见森林的感觉, 因为你写的是子步骤,而不是核心流程

在Template Method中, 蕴含着一种“不要调用我, 我来调用你”的反向控制结构

其他

  1. 基类的析构函数要声明为虚函数
  2. 在面向对象中, 扩展一般为:继承+多态
  3. 如何实现晚绑定, 在面向对象中最基本和最基础的做法就是:虚函数, 但是在c++中还可以使用函数指针/函数对象等, 虽然虚函数的实现机制就是利用函数指针
  4. 被Template Method调用的函数可以有实现也可以没有实现, 一般声明和设计为protected

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

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

相关文章

编写Hello World!,开启cpp人生

一、具体步骤 1.、安装Visual Studio2019(网上教程很多&#xff09;并打开。 2、新建项目 首先配置新项目 其中 解决方案包含项目 然后添加cpp文件并编写代码 代码如下 #include <iostream> using namespace std; int main() {cout << "Hello World~&qu…

electron TodoList网页应用打包成linux deb、AppImage应用

这里用的是windows的wsl的ubuntu环境 electron应用打包linux应用需要linux下打包&#xff0c;这里用windows的wsl的ubuntu环境进行操作 1&#xff09;linux ubuntu安装nodejs、electron 安装nodejs&#xff1a; sudo apt update sudo apt upgrade ##快捷安装 curl -fsSL http…

[Day 35] 區塊鏈與人工智能的聯動應用:理論、技術與實踐

區塊鏈的分布式存儲技術 區塊鏈技術自2008年比特幣白皮書發表以來&#xff0c;已經成為一種革命性的技術&#xff0c;帶來了許多創新。區塊鏈本質上是一個去中心化的分布式賬本&#xff0c;每個節點都持有賬本的副本&#xff0c;並參與記錄和驗證交易。分布式存儲是區塊鏈的重…

在SAP中创建主数据的常用BAPI

科目主数据: BAPI_FINANCIAL_ACCOUNTING_DOCUMENT_CREATE &#xff1a;用于创建财务会计凭证。 成本中心: BAPI_COSTCENTER_CREATEMULTIPLE &#xff1a;用于创建多个成本中心。BAPI_COSTCENTER_CHANGEMULTIPLE &#xff1a;用于修改多个成本中心。 利润中心: BAPI_PROFITCEN…

机器学习驱动的智能化电池管理技术与应用

目录 主要内容 电池管理技术概述 电池的工作原理与关键性能指标 电池管理系统的核心功能 SOC估计 SOH估计 寿命预测 故障诊断 人工智能机器学习 基础 人工智能的发展 机器学习的关键概念 机器学习在电池管理中的应用案例介绍 人工智能在电池荷电状态估计中的…

小猪佩奇.js

闲着没事 使用js 画一个小猪佩奇把 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</tit…

力扣第三十三题——搜索旋转排序数组

内容介绍 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], ..., nums[n-1], nums[0], num…

UDP进行端口转发时,数据丢失率太高怎么办

在网络通信中,UDP (用户数据报协议) 因其低延迟和高效率而被广泛使用。然而,当使用UDP进行端口转发时,我们可能会遇到数据丢失率高的问题。本文将探讨这个问题的原因及其解决方案,特别关注如何通过调整缓冲区大小来改善情况。 问题根源 UDP数据包丢失可能由多种因素导致,包括…

UDP/TCP协议解析

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

Elasticsearch:跨集群使用 ES|QL

警告&#xff1a;ES|QL 的跨集群搜索目前处于技术预览阶段&#xff0c;可能会在未来版本中更改或删除。Elastic 将努力解决任何问题&#xff0c;但技术预览中的功能不受官方 GA 功能的支持 SLA 约束。 使用 ES|QL&#xff0c;你可以跨多个集群执行单个查询。 前提&#xff1a; …

实战解读:Llama Guard 3 Prompt Guard

前序研究&#xff1a;实战解读&#xff1a;Llama 3 安全性对抗分析 近日&#xff0c;腾讯朱雀实验室又针对 Llama 3.1 安全性做了进一步解读。 2024年7月23日晚&#xff0c;随着Llama3.1的发布&#xff0c;Meta正式提出了“Llama系统”的概念&#xff0c;通过系统级的安全组件对…

谷粒商城实战笔记-62-商品服务-API-品牌管理-OSS整合测试

文章目录 一&#xff0c;Java中上传文件到阿里云OSS1&#xff0c;整合阿里云OSS2&#xff0c;测试上传文件 二&#xff0c;Java中整合阿里云OSS服务指南引言准备工作1. 注册阿里云账号2. 获取Access Key3. 添加依赖 实现OSS客户端1. 初始化OSSClient2. 创建Bucket3. 上传文件4.…

自定义 RAG 工作流:在 IDE 中结合 RAG 编排,构建可信的编码智能体

构建编码智能体并非一件容易的事。结合我们在 AutoDev、ArchGuard Co-mate、ChocoBuilder 等智能体项目的经验&#xff0c;我们开始思考在 Shire 语言中提供一种新的 RAG 工作流。结合我们先前构建的 IDE 基础设施&#xff08;代码生成、代码校验、代码执行等接口&#xff09;&…

基于PaddleClas的人物年龄分类项目

目录 一、任务概述 二、算法研发 2.1 下载数据集 2.2 数据集预处理 2.3 安装PaddleClas套件 2.4 算法训练 2.5 静态图导出 2.6 静态图推理 三、小结 一、任务概述 最近遇到个需求&#xff0c;需要将图像中的人物区分为成人和小孩&#xff0c;这是一个典型的二分类问题…

AI学习指南机器学习篇-SOM在数据聚类和可视化中的应用

AI学习指南机器学习篇 - SOM在数据聚类和可视化中的应用 引言 在机器学习领域&#xff0c;数据聚类和可视化是非常重要的任务。传统的聚类算法如K-means、DBSCAN等在一些场景下表现良好&#xff0c;但对于高维数据的聚类和可视化而言&#xff0c;它们的效果会受到限制。Self-…

Leetcode3219. 切蛋糕的最小总开销 II

Every day a Leetcode 题目来源&#xff1a;3219. 切蛋糕的最小总开销 II 解法1&#xff1a;贪心 谁的开销更大&#xff0c;就先切谁&#xff0c;并且这个先后顺序与切的次数无关。 代码&#xff1a; /** lc appleetcode.cn id3219 langcpp** [3219] 切蛋糕的最小总开销 I…

ubuntu20.04服务器搭建mongodb7

安装参考自mongo官网&#xff1a;在 Ubuntu 上安装 MongoDB Community Edition - MongoDB 手册 v7.0 MongoDB 版本 本教程安装的是 MongoDB 7.0 Community Edition。想要安装不同版本的 MongoDB Community Edition&#xff0c;请移步本页面左上角的版本下拉菜单&#xff0c;选…

ubuntu递归下载deb安装包,解决离线依赖问题

ubuntu递归下载安装包 主要针对离线环境的电脑安装deb包。 将下面的build-essential换成自己需要安装的包&#xff0c;虽然下面代码会递归下载依赖安装包&#xff0c;但是在离线环境下仍然可能会出现依赖包为配置问题。 因此&#xff0c;根据报错&#xff0c;手动递归下载报错…

【SQL 新手教程 1/20】SQL语言MySQL数据库 简介

&#x1f497; 什么是SQL&#xff1f;⭐ (Structured Query Language) 结构化查询语言&#xff0c;是访问和处理关系数据库的计算机标准语言 无论用什么编程语言&#xff08;Java、Python、C……&#xff09;编写程序&#xff0c;只要涉及到操作关系数据库都必须通过SQL来完成 …

4招清洁法,清理电脑无死角,焕然一新效率高

随着时间的积累&#xff0c;电脑内部可能会堆积起大量的垃圾文件、缓存数据和无用程序。因此&#xff0c;定期清理电脑是很有必要的。为了让你的电脑重新焕发生机&#xff0c;提高工作效率&#xff0c;本文将为你介绍4招实用的清洁法&#xff0c;助你轻松清理电脑死角&#xff…