C++设计模式:构建器模式(九)

news2024/7/5 0:14:40
1、定义与动机
  • 定义:将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同的表示(变化)

  • 动机:

    • 在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构建而成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定
    • 如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?
  • 个人理解:构建器模式严格来说是在Template Method方法的基础上进行拆分,将表示和构建过程相分离拆成一个更加复杂但耦合度更低的代码。

2、案例分析
  • 假设需要构建一栋房子,需要墙、窗户、房顶、地板等需求,但是所需要的房子是木头还是石头还是其他材料的房子并不清楚
  • 可以很容易的使用Template Method模式写出一个伪代码,解决依赖倒置问题即可。
2.1、模板方法(一)
class House{
public:
    void Init(){
        // 构建墙
        this->BuilderWall();
        // 构建四个窗户
        for(int i = 0;i < 4;i++){
            this->BuilderWindows();
        }
        // 是否需要铺地板
        if(this->BuilderFlag()){
            this->BuilderFloor();
        }
        // 构建房顶
        this->BuilderRoof();
    }
    virtual ~House(){

    }
protected:
    virtual void BuilderWall() = 0;
    virtual void BuilderWindows() = 0;
    virtual bool BuilderFlag() = 0;
    virtual void BuilderFloor() = 0;
    virtual void BuilderRoof() = 0;
};

class StoneHouse: public House{
public:
    virtual ~StoneHouse(){

    }
protected:
    virtual void BuilderWall(){

    }
    virtual void BuilderWindows(){

    }
    virtual bool BuilderFlag(){
        return true;
    }
    virtual void BuilderFloor(){

    }
    virtual void BuilderRoof(){

    }
};

int main()
{
    House *house = new StoneHouse();
    house->Init();
}

其实这个代码写到这里已经可以了,可以不继续优化也不需要使用构建器模式。

2.2、构建器模式
  • 一个类的功能不能太复杂太过于庞大,当类的行为代码太多时可以考虑重构,将对象的表示和构建过程分离提取多个单独的类
  • 具体思路:
    • House和HouseBuilder基类,分别是一个东西的表示和构建过程
    • 对于House基类可以有多种多样的House,StoneHouse、WoodHouse、CrystalHouse…
    • 对于HouseBuilder基类为每种房子的构建提供具体的Builder构建器,其应该组合一个House基类
    • 由于构建房子的一个基本流程(算法骨架)是大致相同(相对稳定)的,因此可以将这个大致流程(算法骨架)单独提取出一个类,通过多态的性质传入不同的XXXHouseBuilder构建器进行构建不同的房子。
class House{
protected:
    Wall wall;
    Window window;
public:
    virtual ~House(){

    }
    // ...
};

class StoneHouse: public House{
public:
    virtual ~StoneHouse(){

    }
};

class HouseBuilder{
public:
    House* GetResult(){
        return house;
    }
    virtual ~HouseBuilder(){

    }
protected:
    House *house;
    virtual void BuilderWall() = 0;
    virtual void BuilderWindows() = 0;
    virtual bool BuilderFlag() = 0;
    virtual void BuilderFloor() = 0;
    virtual void BuilderRoof() = 0;
};

class StoneHouseBuilder: public HouseBuilder{
protected:
    virtual void BuilderWall(){
//        house->wall;...
    }
    virtual void BuilderWindows(){
//        house->window;...
    }
    virtual bool BuilderFlag(){

    }
    virtual void BuilderFloor(){

    }
    virtual void BuilderRoof(){

    }
};

class HouseDirector{
public:
    HouseBuilder* houseBuilder;
    HouseDirector(HouseBuilder* _houseBuilder): houseBuilder(_houseBuilder){

    }
    House *Construct(){
        // 构建墙
        houseBuilder->BuilderWall();
        // 构建四个窗户
        for(int i = 0;i < 4;i++){
            houseBuilder->BuilderWindows();
        }
        // 是否需要铺地板
        if(houseBuilder->BuilderFlag()){
            houseBuilder->BuilderFloor();
        }
        // 构建房顶
        houseBuilder->BuilderRoof();
        return houseBuilder->GetResult();
    }
};
3、总结
  • Builder模式主要用于“分步构建一个复杂的对象”。在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。
  • 变化点在哪里,封装哪里——Builder模式主要在于应对“复杂对象各个部分”的频繁需求变动。其缺点在于难以应对“分步骤构建算法”的需求变动。(稳定点就是缺点)
  • Builder模式中,需要注意不同语言中构造器内部调用虚函数的差别(C++ vs Java)
    • C++中无法再父类的构造方法中调用子类的虚函数(动态绑定),因为子类在此时还没有构造出来,此时如果在构造方法中调用虚函数,那么将会是静态绑定,意味着调用父类自己的虚函数。而Java等语言不是

在这里插入图片描述

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

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

相关文章

基于SSM的课程进度管理系统的设计与实现

摘要&#xff1a; 在信息技术飞速发展的当下&#xff0c; 借助互联网平台以及功能性系统的支持&#xff0c;人们获取信息以及信息整合的通道越来越多元化。系统和平台帮助人们实现了信息的共享&#xff0c;同时帮助人们更加直观的看到成果和过程的变动。以课程进度管理为例&…

python使用uiautomator2操作雷电模拟器9找图

接上篇文章python使用uiautomator2操作雷电模拟器9并遇到解决adb 连接emulator-5554 unauthorized问题-CSDN博客 搭建好uiautomator2后&#xff0c;主要就是使用了。 本文就利用uiautomator2的截屏、模拟点击和aircv的找图功能&#xff0c;实现对指定寻找的图片的位置的点击。…

HikariPool-1 - jdbcUrl is required with driverClassName.

文章目录 前言一、问题提示二、如何改进1.原来配置2.应该修改成 总结 前言 这是在配置数据库发生多数据源产生的错误 一、问题提示 二、如何改进 1.原来配置 2.应该修改成 总结 以上就是今天要讲的内容&#xff0c;本文仅仅简单介绍了springboot多数据源报错问题

Leetcode算法训练日记 | day17

一、平衡二叉树 1.题目 Leetcode&#xff1a;第 110 题 给定一个二叉树&#xff0c;判断它是否是 平衡二叉树 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;true示例 2&#xff1a; 输入&#xff1a;root [1,2,2,3,3,null,null,4,4]…

旋转链表--快慢指针思想

相似题型&#xff1a;删除链表的第倒数第n个节点&#xff0c;建议先做&#xff0c;有利于理解 class Solution {public ListNode rotateRight(ListNode head, int k) {ListNode prehead;ListNode firsthead;ListNode secondhead;ListNode lenpre;int length1;if(headnull)retu…

Linux——fork复制进程

1)shell: 在计算机科学中&#xff0c;Shell俗称壳&#xff08;用来区别于核&#xff09;&#xff0c;是指“为使用者提供操作界面”的软件&#xff08;command interpreter&#xff0c;命令解析器&#xff09;。它类似于DOS下的COMMAND.COM和后来的cmd.exe。它接收用户命令&…

R数据分析:网状meta分析的理解与实操

meta分析之前有给大家写过&#xff0c;但是meta分析只能比较两个方法。经常是被用来证明在现有研究中显示矛盾结果的干预方法到底有没有效的时候使用&#xff0c;通过证据综合得到某种干预到底有没有用的结论。但是如果我要证明好几种方法到底哪个最优&#xff0c;这个时候meta…

谈谈功率IC巨头—士兰微

大家好&#xff0c;我是砖一。 今天给大家分享一下士兰微电子公司&#xff0c;&#xff0c;有做功率元器件&开关电源和IC的朋友可以了解一下&#xff0c;希望对你有用~ 1 公司介绍 士兰微电子成立于1997年&#xff0c;于2003年上市&#xff0c;总部位于杭州&#xff0c;…

智能面试——录音及播放下载js-audio-recorder — post请求,formdata传参

录音插件 js-audio-recorder bug&#xff1a;本地调试调取不起来麦克风 浏览器配置安全域名 chrome://flags/Insecure origins treated as secure输入域名即可电脑需要连接上耳机 <template><div class"BaseRecorder"><div class"BaseRecorder-r…

seo调优

SEO 网站地图&#xff1a;sitemap.xmlrobots.txtxxx.com/www.xxx.com 解析到服务器&#xff0c;xxx.com 301 到 www.xxx.comhttps百度站点管理标题描述关键词标签语义化内链外链死链链接html结尾友情链接前端架构 注意&#xff1a;已收录链接&#xff0c;禁止改变链接地址 ro…

【C++第三阶段】deque容器评委打分案例

以下内容仅为当前认识&#xff0c;可能有不足之处&#xff0c;欢迎讨论&#xff01; 文章目录 构造函数赋值操作大小操作插入删除数据存取排序评委评分案例描述 deque容器 双端数组&#xff0c;可以对头端插入删除操作。 如下图所示。 头部有插入删除操作&#xff0c;尾部亦然…

国内如何实现GPT升级付款

本来想找国外的朋友代付的&#xff0c;但是他告诉我他的信用卡已经被绑定了他也升级了所以只能自己想办法了。就在一位博主下边发现了这个方法真的可以。只是需要与支付宝验证信息。刚开始不敢付款害怕被骗哈哈&#xff0c;我反诈骗意识绝对杠杠的 该方法就是我们办理一张虚拟…

After Effects 2024 中文激活版 高效工作流程与创新的视觉特效 mac/win

After Effects 2024是Adobe公司推出的一款专业视频特效制作软件&#xff0c;广泛应用于电影、电视、动画等媒体制作领域。它凭借强大的功能和灵活的操作&#xff0c;帮助用户轻松创建电影级影片字幕、片头和过渡效果&#xff0c;以及实现立体效果和动态场景的切换。 同时&#…

Java-接口—知识(基础)

承接上一节&#xff0c;我们讨论了抽象类和抽象方法。 那我们尝试在抽象的道路上走的更远一点&#xff0c;先来总结一下抽象&#xff1b; 抽象类&#xff1a;类中的属性规范了子类必须有什么样的特征&#xff0c;有什么状态。类中的方法规范了子类必须有什么行为&#xff0c;…

【Spring Security】2.实现最简单的身份验证

文章目录 一、找到官网的身份认证&#xff08;authentication&#xff09;示例代码二、实现最简单的身份验证1、创建Spring Boot项目2、创建IndexController3、创建index.html4、启动项目测试Controller 三、{/logout}的作用四、页面样式无法加载的问题 一、找到官网的身份认证…

文本处理常见命令

目录 前言-了解Linux目录结构 一、cat-查看文件内容 1.表现形式 2.常用选项 3.示例 二、more-查看文件内容 1.表现形式 2.交互操作方法 3.示例 三、less-查看文件内容 1.表现形式 2.交互操作方法 四、head-从头查看文件内容 五、tail-从尾查看文件内容 六、wc-统…

设计模式学习笔记 - 设计模式与范式 -行为型:10.迭代器模式(中):遍历集合时,为什么不能增删集合?

概述 上篇文章&#xff0c;我们通过给 ArrayList 和 LinkedList 容器实现迭代器&#xff0c;学习了迭代器模式的原理、实现和设计意图。迭代器模式主要主要是解耦容器代码和遍历代码。 本章&#xff0c;我们来深挖一下&#xff0c;如果在使用迭代器遍历集合的同时增加、删除集…

1999-2022年各省研究与试验发展人员全时当量数据/省研发人员全时当量数据/(RD)人员全时当量(无缺失)

1999-2022年各省研究与试验发展人员全时当量数据/省研发人员全时当量数据/(R&D)人员全时当量&#xff08;无缺失&#xff09; 1、时间&#xff1a;1999-2022年 2、来源&#xff1a;科技年鉴 3、指标&#xff1a;研究与试验发展人员全时当量/研发人员全时当量 4、范围&a…

代码随想录算法训练营Day50|LC123 买卖股票的最佳时机IIILC188 买卖股票的最佳时机IV

一句话总结&#xff1a;虽然是困难题&#xff0c;其实都只需要对122 买卖股票的最佳时机II稍作变形即可。 原题链接&#xff1a;123 买卖股票的最佳时机III 相较于买卖股票的最佳时机和股票II来说&#xff0c;本题加了最多操作两次的限制。那么这里实际上就可以直接用滚动数组…

用C代码实现环形缓冲区(ring buf)

用C代码实现环形缓冲区&#xff08;ring buf&#xff09; 概述环境介绍launch.json(没改&#xff09;tasks.json注意 代码ringbuf.cringbuf.hmain.c 测试说明工程代码下载 概述 因嵌入式项目需要&#xff0c;串口接收的数据有很高的周期性发送频率&#xff0c;原方式通过查询接…