设计模式之建造者

建造者(生成器)模式

含义:生成器模式是一种创建型模式,使你能够分步奏创建复杂对象,可使用相同的创建代码生成不同类型和形式的对象。

看图我们就能很好地理解,图中就是工厂中的流水线模式,建造者就好比整条流水线,通过流水线上每个装配点的工人将一个个产品零件组装整合成一个完整的产品即可。

将对象构造代码从具体产品类中抽取出来,并将其放在一个名为生成器的独立对象中。

它可以让你能够分步奏创建复杂对象,不允许其他对象访问正在创建中的产品。

利用相同的物料,不同的组装所产生出的具体内容,就是建造者模式的最终体现。

将一个复杂的构建与其表示分离,使得同样的构建过程可以创建不同的表示。

生成器模式结构

  1. 生成器(Builder)接口声明在所有类型生成器中通用的产品构造步奏。

  2. 具体生成器(Concrete Builders)提供构造过程的不同实现,具体生成器也可以构造不遵循通用接口的产品。

  3. 产品(Products)是最终生成的对象。由不同生成器构造的产品无需数据同一类层次结构或接口。

  4. 主管(Director)类定义调用构造步奏的顺序,这样就可以创建和复用特定的产品配置。

建造者模式主要解决的问题是在软件系统中,有时候面临着一个复杂对象的创建工作,其通常由各部分的子对象用一定的过程构成;由于需求的变化,这个复杂对象的各个部分经常面临着重大的变化,但是将它们组合在一起的过程却相对稳定。

Demo展示

这里我就拿极速物流公司中发货的过程来举例,希望大家能对建造者模式有一个很好的理解。

小A去物流公司发货,他手里面的货物要发送到3个不同的地方,物流公司会根据不同地区有不同的收费标准。可是对于小A来说,他不需要管那些,只需要将三件东西交给收货员,填写好各自货物的收件地址就OK,收货员通过计算出不同收件地址的收费情况给出报价单,告诉小A应付多少钱,小A只需要付款就可以。

这里不同地区收费不一样给出报价单的业务就可以使用我们刚刚学习到的建造者模式来实现,由于不同地方的运输路径,发货方式,包装方式等不同,则收费标准也是不一样的。

类结构描述

  • 发货货物类(基本属性)

  • 发货抽象类(生成器)

  • 各自不同地区的收费类(具体生成器,生成器的实现类)

  • 发货的控制类(主管)

    /// <summary>/// 物流公司发货基类/// 运输方式、包装样式、运输类型/// </summary>public class Matter{/// <summary>/// 包装样式/// </summary>public string PackStyle{get;set;}/// <summary>/// 运输方式/// </summary>public string TransportWay { get; set; }/// <summary>/// 是否有税费/// </summary>public string IsHaveTax { get; set; }/// <summary>/// 总金额/// </summary>/// <returns></returns>public double Money { get; set; }/// <summary>/// 描述信息/// </summary>public string DescriptionInfo { get; set; }}
 /// <summary>/// 发货实现类 :抽象建造者/// </summary>public abstract class SendModelBuilder{protected Matter matter = new Matter();public abstract void BuilderPackStyle();public abstract void BuilderTransportWay();public abstract void BuilderIsHaveTax();public abstract void BuilderMoney();public abstract void BuilderDescriptionInfo();/// <summary>/// 返回一个完整得发货实现类/// </summary>/// <returns></returns>public Matter CreateMatter(){return matter;}}
     /// <summary>/// 日本地区创建者/// </summary>public class RiBenBuilder : SendModelBuilder{public override void BuilderPackStyle(){matter.PackStyle = "木质箱子包装";}public override void BuilderTransportWay(){matter.TransportWay = "水路";}public override void BuilderIsHaveTax(){matter.IsHaveTax = "有";}public override void BuilderMoney(){matter.Money = 1000;}public override void BuilderDescriptionInfo(){matter.DescriptionInfo = "此次运输为水路运输,货物为木质箱子包装,有税费,金额为1000元";}}
    /// <summary>/// 北京地区创建者/// </summary>public class BeiJingBuilder : SendModelBuilder{public override void BuilderPackStyle(){matter.PackStyle = "纸盒";}public override void BuilderTransportWay(){matter.TransportWay = "陆运";}public override void BuilderIsHaveTax(){matter.IsHaveTax = "有";}public override void BuilderMoney(){matter.Money = 50;}public override void BuilderDescriptionInfo(){matter.DescriptionInfo = "此次运输为陆运运输,货物为纸盒包装,无税费,金额为50元";}}
    /// <summary>/// 印度地区创建者/// </summary>public class YinDuBuilder : SendModelBuilder{public override void BuilderPackStyle(){matter.PackStyle = "纸盒包装";           }public override void BuilderTransportWay(){matter.TransportWay = "空运";}public override void BuilderIsHaveTax(){matter.IsHaveTax = "有";}public override void BuilderMoney(){matter.Money = 3000;}public override void BuilderDescriptionInfo(){matter.DescriptionInfo = "此次运输为空运,货物为纸盒包装,有税费,金额为3000元";}}
    /// <summary>/// 急速物流发货创建控制器/// </summary>public class JiSuWuLiuController{public Matter SendModel(SendModelBuilder builder) {builder.BuilderPackStyle();builder.BuilderTransportWay();builder.BuilderIsHaveTax();builder.BuilderMoney();builder.BuilderDescriptionInfo();return builder.CreateMatter();}}

上面罗列出的就是各个类的具体代码实现,下面是测试,目前以北京地区发货举例。

    class Program{static void Main(string[] args){SendModelBuilder smb = new BeiJingBuilder();JiSuWuLiuController director = new JiSuWuLiuController();Matter matter = director.SendModel(smb);Console.WriteLine("包装类型:"+matter.PackStyle);Console.WriteLine("运输方式:" + matter.TransportWay);Console.WriteLine("是否有税费:" + matter.IsHaveTax);Console.WriteLine("运费:" + matter.Money);Console.WriteLine("信息:"+matter.DescriptionInfo);Console.ReadKey();}}
测试结果

可以看到,我们在实现的时候,只是去声明并由directior来调用了BeiJingBuilder的创建者,具体的业务也只是单独在BeiJingBuilder类中去实现。如果我们想换成其余地区的发货,则只需要将声明换掉就可以。

小结

优点:

  • 客户端不需要知道产品内部的组成细节,将产品本身与产品的创建进行分离,也就是解耦,使得相同的创建过程可以创建不同的产品对象。

  • 具体构建独立,增加新的建造者不需要修改原有库,系统扩展方便,符合开闭原则。

  • 控制产品的创建过程很方便。

缺点:

  • 当产品比较多时,导致代码比较冗余,系统变得过于庞大,增加系统的理解难度和运行成本。

  • 此模式主要适用于当各自产品有一定共性的时候,如果产品独立性太强,无相同共性则不适合这个模式。

小寄语

人生短暂,我不想去追求自己看不见的,我只想抓住我能看的见的。

我是阿辉,感谢您的阅读,如果对你有帮助,麻烦点赞、转发  谢谢。

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

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

相关文章

索尼服务器维护时间,索尼云服务器

索尼云服务器 内容精选换一换如果密码丢失、或创建时未设置密码&#xff0c;推荐您在控制台设置登录密码。更新后端云服务器&#xff0c;可修改字段为后端云服务器的名称和权重&#xff0c;可以为性能好的服务器设置更大的权重&#xff0c;用来接收更多的流量。如果后端云服务器…

刚刚,陶哲轩惨遭3个物理学家狠狠打脸,一条数学公式或将引起教科书改革

这波操作把数学界都炸懵了就在刚刚&#xff0c; 3 位物理学家联合数学天才、菲尔兹奖得主陶哲轩&#xff0c;彻底炸翻了数学界。左往右&#xff0c;彼得丹顿、斯蒂芬帕克、张西宁彼得丹顿&#xff08;Peter B.Denton&#xff09;&#xff0c;美国布鲁克黑文国家实验室的助理物理…

教材管理系统紧张开发中

教材管理系统紧张开发中&#xff0c;系统也许不大&#xff0c;可是业务比较复杂、交叉性很强&#xff0c;教学计划、课程代码、教材、供货商、分校点、系部、教师、学生、库存、盘点、结算、数据采集、征订、订购、分发、收费一个都不能少&#xff01;既有C/S三层又有Web模式&a…

Blazor 组件之间使用 EventCallback 进行通信

翻译自 Waqas Anwar 2021年3月28日的文章 《Communication between Blazor Components using EventCallback》 [1]Blazor 应用程序是相互交互的多个 Blazor 组件的集合&#xff0c;我们可以在其他父组件中使用子组件。在实际的应用程序中&#xff0c;将数据或事件信息从一个组件…

***教程十:数据库注入(上)

这一段的教程是笔者&#xff08;这里应该叫整理者&#xff09;由《***X档案》的教程中整理改编而来。不知道是什么时候&#xff0c;B/S结构的软件越来越普及。工程师们为了应对“用户皆白痴”的服务理念&#xff08;就是把用户想像成什么都不会&#xff09;&#xff0c;所以更加…

服务器精益改善系列,精益生产改善的内容是什么?

精益生产管理改善的内容包含了生产管理过程中的方方面面&#xff0c;如果可以准确理解的话&#xff0c;请从以下三个方面来理解&#xff1a;首先是精益生产管理六大产出&#xff0c;即PQCDSM&#xff0c;就是精益生产管理改善的第一层内容。其中PQCDSM分别代表了P&#xff1a;P…

当代大学查寝奇葩操作大赏 | 今日最佳

全世界只有3.14 %的人关注了青少年数学之旅&#xff08;图源 阿粪青&#xff0c;侵权删&#xff09;

mysql学习笔记之mysqlparameter(摘)

在.net中操作数据库的时候。 大家都喜欢用sqlparameter。 parameter是预编译的&#xff0c;可以加快速度&#xff0c;也可以防注入。 在使用mssql的时候用sqlparameter。 在使用mysql的时候使用mysqlparameters。 第一次使用mysql的时候&#xff0c;都经常犯一个错误 比如在使用…

.net LTS3.1升5.0和LTS6.0隐蔽的坑

下面这段代码就是把ascll为0到127值 &#xff0c;转成string&#xff0c;并判断在字符串中的位置&#xff0c;第5&#xff0c;6行代码分别用了两种IndexOf方法的重载。for (var i 0; i < 128; i) {var str1 ((char)i).ToString();var str2 $"---------------{str1}-…

Java正则表达式获取网页所有网址和链接文字

/*获取网址首页的所有网址和链接文字*/import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.MalformedURLException;import java.net.URL;import java.util.ArrayList;import java.util.HashMap;import java.util.Lis…

学习烂到留级,却凭着正经发表的第一篇论文,优雅斩获诺贝尔奖

全世界只有3.14 %的人关注了青少年数学之旅照片里的男人&#xff0c;得意但很谦逊&#xff0c;他是诺贝尔化学奖创设以来最年轻得主——田中耕一。诺贝尔奖通知的那一天 叮铃叮铃叮铃......正在加班的田中耕一掏出手机&#xff0c;这是一个陌生的跨洋电话。电话那头的外国人…

CakePHP Pagination (分頁功能) 加入自己的參數

如果還不知道什麼是 Pagination 或者還不了解如何使用&#xff0c;請參考&#xff1a; CakePHP Pagination (分頁功能) 。通常在管理後台實作時&#xff0c;常設定許多查詢條件來查詢資料&#xff0c;比如&#xff1a;起始、結束時間。通常這些參數都是用GET的方式在傳遞。以下…

基于事件驱动架构构建微服务第2部分:领域对象和业务规则

原文链接&#xff1a;https://logcorner.com/building-microservices-through-event-driven-architecture-part2-domain-objects-and-business-rules/在本文中&#xff0c;我将实现领域模型&#xff1a;EduSync.Speech.Domain这是包含核心域的最内层。它包含我们的领域对象和业…

qt客户端连接服务器不响应,qt判断tcp客户端是否连接服务器

qt判断tcp客户端是否连接服务器 内容精选换一换本章节指导您使用MongoDB客户端&#xff0c;通过弹性云服务器内网方式连接GaussDB(for Mongo)集群实例。操作系统使用场景&#xff1a;弹性云服务器的操作系统以Linux为例&#xff0c;客户端本地使用的计算机系统以Windows为例。目…

谈谈为什么我们需要云原生架构?

未来的软件&#xff0c;从诞生起&#xff0c;就是生在云上&#xff0c;长在云上的。这个说法绝对不是没有根据的&#xff0c;看看现在的互联网大厂在做的事情&#xff0c;你就知道了&#xff1a;阿里宣布成立云原生技术委员会&#xff0c;并投入数十亿大力推动阿里经济体全面云…

服务器系统设计方案,服务器集群方案设计

当前主流的集群方式包括以下几种&#xff1a;1.服务器主备集群方式服务器主-备方式由一台服务器在正常运行状态提供对外服务&#xff0c;其它集群节点作为备份机&#xff0c;备份机在正常状态下不接受外部的应用请求&#xff0c;实时对生产机进行检测&#xff0c;当生产机停机时…

快别发语音了! | 今日最佳

全世界只有3.14 %的人关注了青少年数学之旅&#xff08;图源千叶的堕天使绅士猫_呜喵0w0&#xff0c;侵权删&#xff09;我们无论遇到什么困难&#xff0c;都不要怕&#xff0c;微笑着面对它&#xff01;消除恐惧的最好方法就是面对恐惧&#xff01;

软件项目管理概览----版本控制

随着软件项目规模的不断扩大&#xff0c;项目管理的作用变得越来越重要。如果一个需要长期维护的项目不能得到很好的管理与控制&#xff0c;“软件腐败”就会发生&#xff0c;用不了多久&#xff0c;我们的程序可能就会像一团拌好的炸酱面一样难以找到头绪&#xff0c;维护的成…

设计模式之原型

原型模式介绍完整拷贝原型模式主要解决的问题就是创建重复对象&#xff0c;而这部分对象内容本身比较复杂&#xff0c;生成过程可能从库或者RPC接口中获取数据的耗时较长&#xff0c;因此采用克隆的方式节省时间。原型模式是一种创建型设计模式&#xff0c;使你能够复制已有对象…

华为服务器停止响应,windows服务器停止工作

windows服务器停止工作 内容精选换一换无法通过远程桌面连接裸金属服务器时&#xff0c;我们推荐您按照以下思路排查问题。检查是否符合登录条件检查网络是否正常检查防火墙配置是否正常远程访问端口配置异常尝试重启裸金属服务器确认是否已经按照裸金属服务器登录前的准备工作…