我的设计模式之旅(4)——生成器(建造者)模式Builder

Builder模式也是创建型模式中的一种。主要用来应对构成复杂但构成结构和顺序相对稳定的对象的创建工作。目的是省去在对象发生变化时,需要修改代码中每一处对象创建的地方,应用这种模式,可以在一个复杂对象的内部结构(由许多其他子对象构成的结构)发生变化时,仅需要对对象有所修改,而复杂对象与其他的对象之间的关系、行为不需要进行修改。

其实这就是这个创建型模式应用的动机:在软件系统中,有时面临着一个复杂对象的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

GOF

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

下面举一个例子,来说明这种应用,比如说买电脑中的装机,根据消费者不同的需求,我们要提供不同品牌不同配置的电脑。

装机器就像Builder模式描述的一样,组装成机器的方法(即用子对象构建对象的算法)是稳定的,但是根据客户的需求可能对机器现有配置要求升级,则只是子对象发生了变化,但是这不影响极其的组装方法。

定义组装成电脑需要的设备,这里为了代码量少一些,简化了电脑的构建,粗略的分为CPU、主板、内存、硬盘、键盘、鼠标。首先构建它们对应的抽象类。

     // 电脑

     public abstract class Computer

     {

     }

 

     // CPU

     public abstract class CPU

     {

     }

     // 主板

     public abstract class Mainboard

     {

     }

     // 内存

     public abstract class Memory

     {

     }

     // 硬盘

     public abstract class Harddisk

     {

     }

     // 键盘

     public abstract class Keyboard

     {

     }

     // 鼠标

     public abstract class Mouse

     {

     }

然后,就可以定义构建组装电脑需要的配件的抽象方法。

     public abstract class ComputerBuilder

     {

         public abstract void BuildCPU();

         public abstract void BuildMainboard();

         public abstract void BuildMemory();

         public abstract void BuildHarddisk();

         public abstract void BuildKeyboard();

         public abstract void BuildMouse();

 

         public abstract Computer GetComputer();

     }

这里仅提供了一种品牌机的标准配置IBM。这时就可以来构建我们实际需要的IBM配件(实际子对象)了。

     // IBM电脑

     public class IBMComputer : Computer

     {

     }

 

     // IBMCPU

     public class IBMCPU : CPU

     {

     }

     // IBM主板

     public class IBMMainboard : Mainboard

     {

     }

     // IBM内存

     public class IBMMemory : Memory

     {

     }

     // IBM硬盘

     public class IBMHarddisk : Harddisk

     {

     }

     // IBM键盘

     public class IBMKeyboard : Keyboard

     {

     }

     // IBM鼠标

     public class IBMMouse : Mouse

     {

     }

到这里我们就需要定义,组装IBM配件的方法了。为了简单,这里又定义了一个用来存储实际需要的配件集合,用来存储我们构建出来的配件(子对象)。

     public class AssemblyComputer

     {

         // 组装起来的电脑配件

         ArrayList accessories = new ArrayList();

 

         public void Add(string part)

         {

              accessories.Add(part);

         }

 

         public void ShowDetails ()

         {

              Console.WriteLine( "Computer Accessories: " );

 

              foreach(string part in accessories)

                   Console.WriteLine(part);

         }

     }

这时我们的ComputerBuilder方法和集成自它的实际构建方法IBMComputerBuilder就需要有所修改,返回一个我们建立的辅助信息存储类型的对象AssemblyComputer。以下为修改后的IBM电脑子对象构建类。

     public class IBMComputerBuilder : ComputerBuilder

     {

         AssemblyComputer ac = new AssemblyComputer();

 

         public override void BuildCPU()

         {

              ac.Add("IBMCPU");

         }

         public override void BuildMainboard()

         {

              ac.Add("IBMMainboard");

         }

         public override void BuildMemory()

         {

              ac.Add("IBMMemory");

         }

         public override void BuildHarddisk()

         {

              ac.Add("IBMHarddisk");

         }

         public override void BuildKeyboard()

         {

              ac.Add("IBMKeyboard");

         }

         public override void BuildMouse()

         {

              ac.Add("IBMMouse");

         }

 

         public override AssemblyComputer GetComputer()

         {

              return ac;

         }

     }

相应的抽象类也做修改。

     public abstract class ComputerBuilder

     {

         public abstract void BuildCPU();

         public abstract void BuildMainboard();

         public abstract void BuildMemory();

         public abstract void BuildHarddisk();

         public abstract void BuildKeyboard();

         public abstract void BuildMouse();

 

         public abstract AssemblyComputer GetComputer();

     }

最后,我们定这个电脑的配置类,就是这台电脑的实际配置。

     public class ComputerConfiguration

     {

         public static AssemblyComputer CreateComputer(ComputerBuilder computerbuilder)

         {

              computerbuilder.BuildCPU();

              computerbuilder.BuildMainboard();

              computerbuilder.BuildMemory();

              computerbuilder.BuildHarddisk();

              computerbuilder.BuildKeyboard();

              computerbuilder.BuildMouse();

 

              return computerbuilder.GetComputer();

         }

     }

其中的CreateComputer方法就是构建了一个电脑的实际配置例子。这里有一点需要强调的就是,这台电脑需要的配件是稳定的,需要CPU、主板、内存、硬盘、键盘、鼠标。至于具体需要什么牌子的,很可能客户就不要IBM的键盘鼠标,而需要一套罗技的键盘和鼠标,这时只要修改我们IBM的构建类,或者是添加一个新的自定义电脑配置类,然后在这个自定义构建类中定义我们需要的具体配件,而这些配件(子对象)构建出来的电脑对象的构建过程是不变的。

这样,我们在客户程序中使用定义好的对象时可以使用下面的代码。

     AssemblyComputer ac = ComputerConfiguration.CreateComputer(new IBMComputerBuilder());

     ac.ShowDetails();

     Console.ReadLine();

首先定一个电脑配置,然后使用一个需要的配置的生成器,最后将电脑配置呈现出来。

得到执行结果:

Computer Accessories:

IBMCPU

IBMMainboard

IBMMemory

IBMHarddisk

IBMKeyboard

IBMMouse

 

看到这段代码可能大家还是感觉有新的配置后在维护的时候仍然需要修改new IBMComputerBuilder()这里,我们可以使用反射机制来解决这种问题,这样就解决了扩展上不许重新进行编译的问题。如果以前的有所修改那就直接替换掉相应的DLL程序集就可以了。方便了以后的维护扩展工作。

 

 

转载于:https://www.cnblogs.com/Bear-Study-Hard/archive/2006/10/24/538606.html

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

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

相关文章

LeetCode—309. 最佳买卖股票时机含冷冻期

309. 最佳买卖股票时机含冷冻期 题目描述: 给定一个整数数组prices,其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票&#xff…

innosetup区分正常状态和静默安装状态(通过传递的参数)

命令行运行程序,如: myprogram.exe /abc /bcd 如果我们想获取其中的参数,“/abc”、“/bcd” 1. 直接使用innosetup自带的方法, GetCmdTail() 将所有参数作为一个字符串返回,安装和卸载都适用 注意:如果打…

测试计划排期内容和格式要求,测试邮件回复统一格式

公司最近在做一些测试流程规范,每次项目立项后,需要确认本次项目测试负责人,由测试项目负责人参加完需求评审后,协调资源 给出测试计划排期与对应子模块负责人员到项目经理处。 下面提供给大家一个测试计划排期内容和格式文档 2.测…

LeetCode—剑指 Offer 4、9、26、35、53

剑指 Offer 4. 二维数组中的查找、9. 用两个栈实现队列、26. 树的子结构、35. 复杂链表的复制、53 - I. 在排序数组中查找数字 I 题目描述: [4] 在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺…

Ubuntu 安装 JDK 问题

2019独角兽企业重金招聘Python工程师标准>>> 1. 下载并解压缩 2. mv到/usr/lib/jdk 3. 在~/.bashrc文件末尾添加环境变量 export JAVA_HOME/usr/lib/jdkexport CLASSPATH${JAVA_HOME}/libexport PATH${JAVA_HOME}/bin:$PATH 4. 重启终端,输入javac -vers…

Asp.net中水晶报表的使用

在我们对VS.Net中的水晶报表(Crystal Reports)进行研究之前,我和我朋友对如何将这个复杂的东东加入我们的Web应用有着非常的好奇心。一周以后,在阅读了大量的“HOWTO”文档之后,我们成功地将一些简单的报告加入到了我们…

2011-8-31 身体欠佳

1. 前几日明显感到身体欠佳,熬夜很难受,以往搞到1点问题不大的, 老了啊。 经过几天作息时间的调整,回家不开电脑,23点之前上床,在加上食疗,今天缓过来了。 看来有必要把生活节奏放慢一点&#x…

Scala学习(一)--Scala基础学习

Scala基础学习 摘要: 在篇主要内容:如何把Scala当做工业级的便携计算器使用,如何用Scala处理数字以及其他算术操作。在这个过程中,我们将介绍一系列重要的Scala概念和惯用法。同时你还将学到作为初学者如何浏览Scaladoc文档 1. 使…

Test live writer

拷贝屏幕来的图片 转载于:https://www.cnblogs.com/huobazi/archive/2006/11/19/565070.html

LeetCode—剑指 Offer 10 - I、II 斐波那契数列、青蛙跳台阶问题 63. 股票的最大利润

剑指 Offer 10 - I、II 斐波那契数列、青蛙跳台阶问题 63. 股票的最大利润 题目描述: [I] 斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。答案需要取模 1e97(1000000007),如计算初始结果为…

Hadoop学习笔记—2.不怕故障的海量存储:HDFS基础入门

一.HDFS出现的背景 随着社会的进步,需要处理数据量越来越多,在一个操作系统管辖的范围存不下了,那么就分配到更多的操作系统管理的磁盘中,但是却不方便管理和维护—>因此,迫切需要一种系统来管理多台机器上的文件&a…

LeetCode—<动态规划专项>剑指 Offer 42、46、47、48

剑指 Offer 42. 连续子数组的最大和、剑指 Offer 46. 把数字翻译成字符串、剑指 Offer 47. 礼物的最大价值、剑指 Offer 48. 最长不含重复字符的子字符串 题目描述: [42] [46] [47] [48] 考察重点:第42题要计算最大子数组和,考虑第i位…

操作系统核心原理-5.内存管理(下):段式内存管理

一、分页系统的缺点 分页系统存在的一个无法容忍,同时也是分页系统无法解决的一个缺点就是:一个进程只能占有一个虚拟地址空间。在此种限制下,一个程序的大小至多只能和虚拟空间一样大,其所有内容都必须从这个共同的虚拟空间内分配…

LeetCode—<双指针专项>剑指 Offer 18、21、22、25、52、57、58 - I

剑指 Offer 18. 删除链表的节点、21. 调整数组顺序使奇数位于偶数前面、22. 链表中倒数第k个节点、25. 合并两个排序的链表、52. 两个链表的第一个公共节点、57. 和为s的两个数字、58 - I. 翻转单词顺序 题目描述: [18] 给定单向链表的头指针和一个要删除的节点的值…

Android应用程序绑定服务(bindService)的过程源代码分析

Android应用程序组件Service与Activity一样,既可以在新的进程中启动,也可以在应用程序进程内部启动;前面我们已经分析了在新的进程中启动Service的过程,本文将要介绍在应用程序内部绑定Service的过程,这是一种在应用程…

Bootstrap系列 -- 8. 代码显示

一. Bootstrap中的代码块 代码块一般在博客中使用的较多&#xff0c;比较博客园中提供的贴代码. 在Bootstrap中提供了三种形式的代码显示 1. 使用<code></code>来显示单行内联代码 2. 使用<pre></pre>来显示多行块代码 3. 使用<kbd></kbd>…

PowerDesigner12对SQL2005反向工程问题.

用PowerDesigner12利用ODBC连接SQL2005进行反向工程&#xff0c;总分报错[Microsoft][ODBC SQL Server Driver][SQL Server]未能准备评语句SQLSTATE37000解决办法&#xff1a;把&#xff02;更改默认的数据库为&#xff02;这个选项去掉在中选择要进行操做的数据库.转载于:http…

LeetCode—<搜索与回溯专项>剑指 Offer 12、13、34、36、54

剑指 Offer 12. 矩阵中的路径、13. 机器人的运动范围、34. 二叉树中和为某一值的路径、36. 二叉搜索树与双向链表、54. 二叉搜索树的第k大节点 题目描述&#xff1a; [12] 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回…

导数--基本概念

转载于:https://www.cnblogs.com/liuys635/p/11242741.html

[导入]创建、查询、修改带名称空间的 XML 文件的例子

XML的应用越来越广泛了&#xff0c;如Vista、Flex编程都将使用 XML&#xff0c;正确掌握XML的各种操作&#xff0c;对提高编程效率至关重要。下面就是一个综合处理带名称空间的XML的例子。 文章来源:http://blog.csdn.net/net_lover/archive/2006/12/18/1447434.aspx 转载于:ht…