面向对象设计模式_生成器模式详解(Builder Pattern)
首先提出一个很容易想到应用场景:
手机的生产过程:手机有非常多的子件(部件),成千上万,不同品牌的手机的生产过程都是复杂而有所区别的,相同品牌的手机在设计上也因客户需求多样化,大到型号,小到颜色,是否配置附件。假设手机的生产过程(这里用方法来代替)可以是几千个方法的叠加过程,每个方法都面临不同的变化,如果将手机的生产过程中的这些方法全部耦合在一个对象里实现,显然是不明智的。
教材书上对生成器模式的解释:生成器模式将复杂对象的构建过程和表示(实现)相分离,使得相同的构建过程可以创建不同的表示。如下图
这里解析一下:"构建过程"(Construct)实则是抽象部分,即稳定的过程框架,它一般不会变化,就像模型中的foreach代码一样,这句代码唯一关联了对象的自身属性(Builders是接口类型IBuilder的集合),仅仅与抽象的接口关联,这完全符合DIP(依赖倒置)原则。手机的生产我们可以抽象成:摄像头生产,电路板生产,......组装手机。这些抽象都是比较稳定的。
“不同的表示”,可以理解为,将这些抽象的过程具体化,并可以用不同的组合形式,顺序来构建(Construct),比如,我可以先生产A,再生产B,然后组装,也可以先B后A,等等。
代码示例:生产一个有很多部件的产品
- public class Director
- {
- //产品架构
- //先生产10个部件1
- //其次再生产4个部件2
- //组装产品
- public List<IBuilder> Builders { get; set; }//将具体过程按序封装到该集合中
- public Director()
- {
- Builders = new List<IBuilder>();//仅依赖抽象接口
- }
- public void Construct()
- {
- foreach (IBuilder b in Builders)//这句代码是非常稳定的,它唯一依赖唯一的自身属性Builders
- {
- b.BuildPart();
- }
- }
- }
- //对每个部件生产的抽象(这个接口算是最抽象级的抽象了)
- public interface IBuilder
- {
- void BuildPart();//每个Builder代表一个部件生产
- }
- //实例化部件的生产过程
- public class Part1Builder : IBuilder
- {
- public void BuildPart()
- {
- Console.WriteLine("完成部件1的生产!");
- }
- }
- //
- public class Part2Builder : IBuilder
- {
- public void BuildPart()
- {
- Console.WriteLine("完成部件2的生产!");
- }
- }
- //对组装过程实例化
- public class ProductBuilder : IBuilder
- {
- public void BuildPart()
- {
- Console.WriteLine("完成产品组装!");
- }
- }
- //测试代码
class Test
{
static void Main(string[] args)
{
Director director = new Director();
for (int i = 0; i <10; i++)
{
director.Builders.Add(new Part1Builder());
}
director.Builders.Add(new Part2Builder());
director.Builders.Add(new ProductBuilder());
director.Construct();
Console.ReadKey();
}
}
有些人对生成器模式有另一种解读,如下图所示:
将抽象的构建过程的实现通过一个实例来实现,接口(IBuilder)中抽象了每一个子过程,每个实现类(ConcreteBuilder)代表一个不同的表示,是一个具体的构建过程。这样当客户需要一种新的形式产品时,就可以具体化一个新的类(ConcreteBuilder)来实现不同的过程(实现抽象化接口),然后在Director的构建方法(Construct)中调用。这实际上比上面一种解读模式稍微提高了些耦合度,同时在统一的接口中的提供很多抽象方法,实际上违背了单一职责原则(职责:变化的原因),扩展修改将变得比较繁重。
上面的两个类图不同之处在于前者使用类对象实现不同的子过程,后者在统一的接口中抽象每个子过程。后者在Director中方法对每个具体实现有所依赖。前者实际解耦性更高。
面向对象设计模式_生成器模式详解(Builder Pattern)的更多相关文章
- 面向对象设计模式_生成器模式解读(Builder Pattern)
首先提出一个很容易想到应用场景: 手机的生产过程:手机有非常多的子件(部件),成千上万,不同品牌的手机的生产过程都是复杂而有所区别的,相同品牌的手机在设计上也因客户需求多样化,大到型号,小到颜色,是否 ...
- 面向对象设计模式_命令模式(Command)解读
在.Net框架中很多对象的方法中都会有Invoke方法,这种方法的设计实际是用了设计模式的命令模式, 模式图如下 其核心思路是将Client 向Receiver发送的命令行为进行抽象(ICommand ...
- 设计模式之 外观模式详解(Service第三者插足,让action与dao分手)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 各位好,LZ今天给各位分享一 ...
- JAVA 设计模式之 工厂模式详解
一.简单工厂模式 简单工厂模式(Simple Factory Pattern)是指由一个工厂对象决定创建出哪一种产品类 的实例.属于创建型模式,但它不属于 GOF,23 种设计模式 (参考资料: ht ...
- 设计模式之迭代器模式详解(foreach的精髓)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 各位好,很久没以LZ的身份和 ...
- javascript设计模式之解释器模式详解
http://www.jb51.net/article/50680.htm 神马是“解释器模式”? 先翻开<GOF>看看Definition:给定一个语言,定义它的文法的一种表示,并定义一 ...
- 设计模式之 原型模式详解(clone方法源码的简单剖析)
作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 原型模式算是JAVA中最简单 ...
- 设计模式——模版方法模式详解(论沉迷LOL对学生的危害)
. 实例介绍 在本例中,我们使用一个常见的场景,我们每个人都上了很多年学,中学大学硕士,有的人天生就是个天才,中学毕业就会微积分,因此得了诺贝尔数学奖:也有的人在大学里学了很多东西,过得很充实很满意 ...
- Java设计模式之状态模式详解
(本文由言念小文原创,转载请注明出处) 在实际工作中经常遇到某个对象,处于不同的状态有不同行为逻辑.且状态之间可以相互迁移的业务场景,特别是在开发通信协议栈类软件中尤为多见.<设计模式之禅> ...
随机推荐
- Dubbo广播模式下报错:Can't assign requested address解决办法
原因: 尝试使用Dubbo的multicast模式,发现一运行就报Can't assign requested address的错误,造成这种原因的主要是系统中开启了IPV6协议(比如window7) ...
- web2 - JavaScript
JavaScript 知识要点 参考教材一 参考教材二 参考教材三 1.JavaScript 和 Java 的关系? 2.JavaScript 在编程中可以做什么? 3.如何在 html 中使用 Ja ...
- ErrorKiller:Failed to decode response: zlib_decode(): data error
先更新composer自己,composer self-update 然后再更新依赖关系 composer update
- nyoj234 吃土豆 01背包
思路:假设我们先只考虑一行,规则就是取了i处的土豆,每一个土豆有两种选择,拿与不拿,那么i-1和i+1处的土豆都不能再取,那么要求某一行的最大取值就用一次动态规划即可,dp(i)表示前i个土豆能取得的 ...
- hive:排序分析函数
基本排序函数 语法: rank()over([partition by col1] order by col2) dense_rank()over([partition by col1] order ...
- CDN中前端层的复制
前端层的复制是为了提高静态内容分发的性能和可扩展性.将静态内容的分发转由边缘服务器来完成是为了解决可扩展性的问题,因为这样做可以避免出现在对等点和广域网链路处的网络拥堵风险,而这两个地方的拥堵是网络延 ...
- Ubuntu版本更替所引发的“血案”
Ubuntu版本更替所引发的"血案" 今天,我兴致很高的装了双系统,并且配置了Linux的网络,接下来就是安装一些软件,来实现我想达到的功能了,结果被一个小小的命令卡的 ...
- hiredis的安装
Hiredis客户端下载地址:https://github.com/antirez/hiredis/zipball/master Hiredis安装步骤: tar zxvf antirez-hired ...
- 嵌入式Linux引导过程之1.6——Xloader的Xloader_Entry
我们已经看完了XLOADER_ENTRY里调用的前两个标号的代码,分别是sys_init和ddr_init.对于一个嵌入式系统来说,这两 个部分的代码是在一开始就执行的,至少是在从bootrom里面的 ...
- free 或delete后指针怎么样了
free()和delete()只是把指针所指向的内存释放掉,但是并没有把指针本身删除,也没有把指针置为NULL; #include<iostream> using namespace st ...