建造者模式
趁着这几天不大忙,赶快把还没有速解决的问题解决一下,比如,写一点设计模式,剩下的时间写写SQL server的总结,然后准备面试!加油!
今天的主角时候建造者模式,按照惯例咱们还是用一个真实的场景来模拟,比如我们宿舍的大神们,会根据自己喜欢的方向寻找一些工作岗位,比如:本屌喜欢林志玲,麻仓优,蛋子喜欢ASP.NET,Oracle!还有大春喜欢WP7,cocos-2d.
宿舍的大神们都喜欢做一些利国利民的好事,比如制作一些视频,和大家一起分享一下最近的学习心得.而本屌呢?喜欢分享点链接.
首先,需要有大春这个类,我们这里叫MrChun,有了MrChun这个就相当于他已经要录制视频了,按照大春的习惯,他喜欢:
第一步:给大家先演示一下今天讲解内容的效果.方法名:DemonstrationEfect()
第二步:根据事先准备的PPT讲解原理.方法名:Principle()
第三步:打开工程分析实现功能的代码.方法名:AnalysisOffCode()
那么大春录制视频的C#代码实现如下:
/// <summary> /// 大春 /// </summary> public class MrChun { //演示效果 public void DemonstrationEfect() { Console.WriteLine("演示WP7-cocos2d,游戏效果"); } //讲解PPT public void Principle() { Console.WriteLine("PPT讲解实现原理"); } //分析代码 public void AnalysisOfCode() { Console.WriteLine("根据原理分析代码"); } }
视频录制完成后发现还有很多人对ASP.NET+Oracle的WEB项目方面的知识感兴趣,这个时候我们的蛋子就为大家录制了一段关于这个技术的视频,那么我们还是需要一个类叫做蛋子,定义名为:MrDan,MrDan录制视频的流程是:
第一步:(与MrChun一样),先给大家演示一下今天讲解内容的效果.方法名:DemonstrationEfect()
第二步:现场代码实现.方法名:Coding()
第三步:分析与回顾关键点.方法名:AnalysisOfKeyPoints()
代码实现如下:
/// <summary> /// 蛋子 /// </summary> public class MrDan { //演示效果 public void DemonstrationEfeect() { Console.WriteLine("演示ASP.NET+Oracle web项目的效果!"); } //代码实现 public void Coding() { Console.WriteLine("一边用代码实现,,一边讲解原理!"); } //分析与回顾关键点 public void AnalysisOfKeyPoints() { } }
这个时候咱们可能会遇到一个问题,就是每个人的讲解方式都有优点,我们需要把每个人讲解过程的优点都提取出来融合成一个固定的规范流程,最后我们决定以后所有的视频都按照这个风格来录制.
第一步:给大家先演示今天讲解内容的效果.
第二步:PPT给大家讲解必须的基础知识与原理.
第三步:代码实现内容.
第四部:关键点分析.
SO,我们如何改造我们上边的代码呢?既然我们可以把一个通用的流程分析出来,将来不管录制的是什么视频,我们都可以这个流程来录制,那么在这里就体现出一种模式的优势----建造者模式.
先来看定义:将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示.
建造者模式类图如下:
指挥者类(Dicrector):用来包含一个Builder的抽象类,,用来表示使用哪个具体的建造者类.
抽象建造者类(Builder):用来抽象product类构建的流程.
具体的建造者类(ConcreteBuilder):用来实现具体建造产品的细节.
产品类(Product):用来承载建造好产品的细节.
以我们上边的场景来看,录制视频的步骤就是构建过程,我们的视频就是表示(产品Product),各位观众就是指挥者,蛋子和大春就是具体的建造者了.
上面场景我们已经将录制视频的统一步骤抽象了出来,那么我们就先把这个抽象的步骤类实现吧,也就是建造者模式中的抽象建造者类(Builder).
代码如下:
/// <summary> /// 抽象建造者类 /// </summary> public abstract class VidioBuilder { /* * 定义我们之前抽象好的四个步骤 * 第一步:给大家先演示一下今天讲解内容的效果 * 第二步:PPT给大家讲解必须的基础知识与原理 * 第三步:代码实现内容 * 第四步:关键点分析 */ //第一步 public abstract void DemonstrationEfect(); //第二步 public abstract void Principle(); //第三步 public abstract void Coding(); //第四步 public abstract void AnalysisOfKeyPoints(); //获得视频 public abstract VidioProduct GetVidio(); }
抽象好了通用的流程当然接下来就可以实现具体根据流程录制的高手们,说要录制视频当然少不了视频这个类了.
代码如下:
/// <summary> /// 视频类 /// </summary> public class VidioProduct { List<string> list = new List<string>(); public void AddVidioContent(string content) { list.Add(content); } public void PlayVidio() { Console.WriteLine("视频内容为: "); foreach (string str in list) { Console.WriteLine(str); } } }
有了视频类,我们就可以找高手来录制视频了,下来就是蛋子和大春出场了.
代码如下:
/// <summary> /// 大春 /// </summary> public class MrChun : VidioBuilder { VidioProduct vidio = new VidioProduct(); //演示效果 public override void DemonstrationEfect() { vidio.AddVidioContent("演示cocos2d游戏效果!"); } //PPT原理讲解 public override void Principle() { vidio.AddVidioContent("PPT讲解实现原理"); } //代码实现 public override void Coding() { vidio.AddVidioContent("代码实现"); } //分析回顾 public override void AnalysisOfKeyPoints() { vidio.AddVidioContent("分析代码实现中的关键技术点"); } //获得录制好的视频 public override VidioProduct GetVidio() { return vidio; } } /// <summary> /// 蛋子 /// </summary> public class MrDan : VidioBuilder { VidioProduct vidio = new VidioProduct(); //演示效果 public override void DemonstrationEfect() { vidio.AddVidioContent("演示ASP.NET+Oracle的WEB效果!"); } //PPT原理讲解 public override void Principle() { vidio.AddVidioContent("PPT讲解实现原理"); } //代码实现 public override void Coding() { vidio.AddVidioContent("代码实现"); } //分析回顾 public override void AnalysisOfKeyPoints() { vidio.AddVidioContent("分析代码实现中的关键技术点"); } //获得录制好的视频 public override VidioProduct GetVidio() { return vidio; } }
接下来我们可以要求两位大神按照我们统一录制视频的顺序录制视频了,那么是谁邀请我们的高手呢?当然是我们的指挥者了(观众),他们来提出需要录制视频的类型.
代码如下:
/// <summary> /// 指挥者 /// </summary> public class GuanZhong { public void BuildingVidio(VidioBuilder builder) { //第一步 builder.DemonstrationEfect(); //第二步 builder.Principle(); //第三步 builder.Coding(); //第四步 builder.AnalysisOfKeyPoints(); } }
OK,接下来我么看一下Main函数是如何调用的吧,代码如下:
class Program { static void Main(string[] args) { GuanZhong guanzhong = new GuanZhong(); VidioBuilder mrChun = new MrChun(); VidioBuilder mrDan = new MrDan(); //首先先让大春录制视频 guanzhong.BuildingVidio(mrChun); VidioProduct v1 = mrChun.GetVidio(); v1.PlayVidio(); //接下来让蛋子录制视频 guanzhong.BuildingVidio(mrDan); VidioProduct v2 = mrDan.GetVidio(); v2.PlayVidio(); Console.Read(); } }
最后的输出结果我就不多说了吧,大家按照上面的内容一点一点的弄,自己看看输出结果怎么样,其实这样大家应该能看到,代码出现了冗余,而且是大量冗余,怎么办?想想.
建造者模式与工厂模式类似,他们都是建造者模式,适用的场景也很相似.一般来说,如果产品的建造很复杂,那么请使用工厂模式;如果产品的建造更复杂,那么请使用建造者模式!