C#学习笔记-建造者模式
题目:用程序画一个小人。
实现:
1 public partial class Form1 : Form 2 { 3 public Form1() 4 { 5 InitializeComponent(); 6 } 7 8 private void button1_Click(object sender, EventArgs e) 9 { 10 Pen p = new Pen(Color.Yellow); 11 Graphics gThin = pictureBox1.CreateGraphics(); 12 13 gThin.DrawEllipse(p, 50, 20, 30, 30); 14 gThin.DrawRectangle(p, 60, 50, 10, 50); 15 gThin.DrawLine(p, 60, 50, 40, 100); 16 gThin.DrawLine(p, 70, 50, 90, 100); 17 gThin.DrawLine(p, 60, 100, 45, 150); 18 gThin.DrawLine(p, 70, 100, 85, 150); 19 20 Graphics gFat = pictureBox2.CreateGraphics(); 21 22 gFat.DrawEllipse(p, 50, 20, 30, 30); 23 gFat.DrawEllipse(p, 45, 50, 40, 50); 24 gFat.DrawLine(p, 50, 50, 30, 100); 25 gFat.DrawLine(p, 80, 50, 100, 100); 26 gFat.DrawLine(p, 60, 100, 45, 150); 27 gFat.DrawLine(p, 70, 100, 85, 150); 28 } 29 }
效果截图:
题目延伸1:将画小人的部分与界面分离开,不让界面的代码显得冗长,也为了防止其他地方调用画小人的情况出现。
解析:
直接将画小人挪到单独的类里即可
PersonBuilder类:
1 class PersonThinBuilder 2 { 3 protected Graphics g; 4 protected Pen p; 5 public PersonThinBuilder(Graphics g,Pen p) 6 { 7 this.g = g; 8 this.p = p; 9 } 10 11 public void Build() 12 { 13 g.DrawEllipse(p, 50, 20, 30, 30); 14 g.DrawRectangle(p, 60, 50, 10, 50); 15 g.DrawLine(p, 60, 50, 40, 100); 16 g.DrawLine(p, 70, 50, 90, 100); 17 g.DrawLine(p, 60, 100, 45, 150); 18 g.DrawLine(p, 70, 100, 85, 150); 19 } 20 } 21 class PersonFatBuilder 22 { 23 protected Graphics g; 24 protected Pen p; 25 26 public PersonFatBuilder(Graphics g, Pen p) 27 { 28 this.g = g; 29 this.p = p; 30 } 31 32 public void Build() 33 { 34 g.DrawEllipse(p, 50, 20, 30, 30); 35 g.DrawEllipse(p, 45, 50, 40, 50); 36 g.DrawLine(p, 50, 50, 30, 100); 37 g.DrawLine(p, 80, 50, 100, 100); 38 g.DrawLine(p, 60, 100, 45, 150); 39 g.DrawLine(p, 70, 100, 85, 150); 40 } 41 }
主函数:
1 private void button1_Click(object sender, EventArgs e) 2 { 3 Pen p = new Pen(Color.Yellow); 4 Graphics gThin = pictureBox1.CreateGraphics(); 5 PersonThinBuilder ptb = new PersonThinBuilder(gThin, p); 6 ptb.Build(); 7 8 Graphics gFat = pictureBox2.CreateGraphics(); 9 PersonFatBuilder pfb = new PersonFatBuilder(gFat, p); 10 pfb.Build(); 11 }
题目延伸2:上面实现了将胖的小人和瘦的小人分别画出来,但是很可能出现,如果当前需要画的人物过多,很可能出现缺胳膊少腿的尴尬情况,考虑到人的组成部分都一致,再细致一下代码。
实现:
1 abstract class PersonBuilder 2 { 3 protected Graphics g; 4 protected Pen p; 5 6 public PersonBuilder(Graphics g,Pen p) 7 { 8 this.p = p; 9 this.g = g; 10 } 11 //将手、脚、身体分开写,就保证了不会忘却画某一个部分 12 public abstract void BuildHead(); 13 public abstract void BuildBody(); 14 public abstract void BuildArmLeft(); 15 public abstract void BuildArmRight(); 16 public abstract void BuildLegLeft(); 17 public abstract void BuildLegRight(); 18 } 19 /// <summary> 20 /// 继承于PersonBuilder类 21 /// 必须全部重写PersonBuilder类里的抽象方法 22 /// 这样保证了在画图的时候不会出现“缺胳膊少腿”的现象 23 /// </summary> 24 class PersonThinBuilder : PersonBuilder 25 { 26 public PersonThinBuilder(Graphics g, Pen p) : base(g, p) 27 { 28 } 29 30 public override void BuildHead() 31 { 32 g.DrawEllipse(p, 50, 20, 30, 30); 33 } 34 public override void BuildBody() 35 { 36 g.DrawRectangle(p, 60, 50, 10, 50); 37 } 38 public override void BuildArmLeft() 39 { 40 g.DrawLine(p, 60, 50, 40, 100); 41 } 42 public override void BuildArmRight() 43 { 44 g.DrawLine(p, 70, 50, 90, 100); 45 } 46 public override void BuildLegLeft() 47 { 48 g.DrawLine(p, 60, 100, 45, 150); 49 } 50 public override void BuildLegRight() 51 { 52 g.DrawLine(p, 70, 100, 85, 150); 53 } 54 } 55 class PersonFatBuilder : PersonBuilder 56 { 57 public PersonFatBuilder(Graphics g, Pen p) : base(g, p) 58 { } 59 60 public override void BuildHead() 61 { 62 g.DrawEllipse(p, 50, 20, 30, 30); 63 } 64 public override void BuildBody() 65 { 66 g.DrawEllipse(p, 45, 50, 40, 50); 67 } 68 public override void BuildArmLeft() 69 { 70 g.DrawLine(p, 50, 50, 30, 100); 71 } 72 public override void BuildArmRight() 73 { 74 g.DrawLine(p, 80, 50, 100, 100); 75 } 76 public override void BuildLegLeft() 77 { 78 g.DrawLine(p, 60, 100, 45, 150); 79 } 80 public override void BuildLegRight() 81 { 82 g.DrawLine(p, 70, 100, 85, 150); 83 } 84 } 85 /// <summary> 86 /// 客户端调用的时候是不需要知道头身手脚这些方法的 87 /// 所以我们需要一个很重要的类,指挥者(Director) 88 /// 用它来控制建造过程,也隔离开了用户与建造过程的关联 89 /// </summary> 90 class PersonDirector 91 { 92 private PersonBuilder pb; 93 public PersonDirector(PersonBuilder pb) 94 { 95 this.pb = pb; 96 } 97 public void CreatePerson() 98 { 99 pb.BuildHead(); 100 pb.BuildBody(); 101 pb.BuildArmLeft(); 102 pb.BuildArmRight(); 103 pb.BuildLegLeft(); 104 pb.BuildLegRight(); 105 } 106 }
解析:
这里用到的就是建造者模式(Builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
它主要是用于创建一些复杂的对象,这些对象的内部构建间的建造顺序通常是稳定的,蛋对象内部的构建通常面临着复杂的变化。
建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要定义一个具体的建造者就可以了。
附:再次简化主函数部分
实现:
PersonBuilder类:
1 abstract class PersonBuilder 2 { 3 protected Graphics g; 4 protected Pen p; 5 6 public PersonBuilder(Graphics g, Pen p) 7 { 8 this.g = g; 9 this.p = p; 10 } 11 12 public abstract void BuildHead(); 13 public abstract void BuildBody(); 14 public abstract void BuildArmLeft(); 15 public abstract void BuildArmRight(); 16 public abstract void BuildLegLeft(); 17 public abstract void BuildLegRight(); 18 } 19 20 class PersonThinBuilder : PersonBuilder 21 { 22 public PersonThinBuilder(Graphics g, Pen p) 23 : base(g, p) 24 { } 25 26 public override void BuildHead() 27 { 28 g.DrawEllipse(p, 50, 20, 30, 30); 29 } 30 31 public override void BuildBody() 32 { 33 g.DrawRectangle(p, 60, 50, 10, 50); 34 } 35 36 public override void BuildArmLeft() 37 { 38 g.DrawLine(p, 60, 50, 40, 100); 39 } 40 41 public override void BuildArmRight() 42 { 43 g.DrawLine(p, 70, 50, 90, 100); 44 } 45 46 public override void BuildLegLeft() 47 { 48 g.DrawLine(p, 60, 100, 45, 150); 49 } 50 51 public override void BuildLegRight() 52 { 53 g.DrawLine(p, 70, 100, 85, 150); 54 } 55 } 56 57 class PersonFatBuilder : PersonBuilder 58 { 59 public PersonFatBuilder(Graphics g, Pen p) 60 : base(g, p) 61 { } 62 63 public override void BuildHead() 64 { 65 g.DrawEllipse(p, 50, 20, 30, 30); 66 } 67 68 public override void BuildBody() 69 { 70 g.DrawEllipse(p, 45, 50, 40, 50); 71 } 72 73 public override void BuildArmLeft() 74 { 75 g.DrawLine(p, 50, 50, 30, 100); 76 } 77 78 public override void BuildArmRight() 79 { 80 g.DrawLine(p, 80, 50, 100, 100); 81 } 82 83 public override void BuildLegLeft() 84 { 85 g.DrawLine(p, 60, 100, 45, 150); 86 } 87 88 public override void BuildLegRight() 89 { 90 g.DrawLine(p, 70, 100, 85, 150); 91 } 92 } 93 94 class PersonDirector 95 { 96 private PersonBuilder pb; 97 /** 98 * Assembly=>程序集 99 */ 100 public PersonDirector(string type,Graphics g,Pen p) 101 { 102 string assemblyName = "建造者模式03"; 103 object[] args = new object[2]; 104 args[0] = g; 105 args[1] = p; 106 107 //Assembly.CreateInstance 方法 (String, Boolean, BindingFlags, Binder, Object[], CultureInfo, Object[]) 108 //从此程序集中查找指定的类型,并使用系统激活器创建它的实例,包括可选的区分大小写搜索并具有指定的区域性、参数和绑定及激活属性。 109 //public object CreateInstance(string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes) 110 this.pb = (PersonBuilder)Assembly.Load(assemblyName).CreateInstance(assemblyName + ".Person" + type + "Builder", false, BindingFlags.Default, null, args, null, null); 111 /** 112 * typeName 113 * 要查找的类型的 Type.FullName。 114 * ignoreCase 115 * 如果为 true,则忽略类型名的大小写;否则,为 false。 116 * bindingAttr 117 * 影响执行搜索的方式的位屏蔽。此值是 BindingFlags 中的位标志的组合。 118 * binder 119 * 一个启用绑定、参数类型强制、成员调用以及通过反射进行 MemberInfo 对象检索的对象。如果 binder 为 空引用(在 Visual Basic 中为 Nothing),则使用默认联编程序。 120 * args 121 * Object 类型的数组,包含要传递给构造函数的参数。此参数数组在数量、顺序和类型方面必须与要调用的构造函数的参数匹配。如果需要默认的构造函数,则 args 必须是空数组或 空引用(在 Visual Basic 中为 Nothing)。 122 * culture 123 * 用于控制类型强制的 CultureInfo 的实例。如果这是 空引用(在 Visual Basic 中为 Nothing),则使用当前线程的 CultureInfo。(例如,这对于将表示 1000 的 String 转换为 Double 值是必需的,因为不同的区域性以不同的方式表示 1000。) 124 * activationAttributes 125 * Object 类型的数组,包含一个或多个可以参与激活的激活属性。激活属性的一个示例是: URLAttribute 126 * 127 * 返回值 128 * 表示此类型且匹配指定条件的 Object 的实例;如果没有找到 typeName,则为 空引用(在 Visual Basic 中为 Nothing)。 129 */ 130 } 131 public void CreatePerson() 132 { 133 pb.BuildHead(); 134 pb.BuildBody(); 135 pb.BuildArmLeft(); 136 pb.BuildArmRight(); 137 pb.BuildLegLeft(); 138 pb.BuildLegRight(); 139 } 140 }
主函数:
1 private void button1_Click(object sender, EventArgs e) 2 { 3 Pen p = new Pen(Color.Yellow); 4 Graphics gThin = pictureBox1.CreateGraphics(); 5 6 PersonDirector pdThin = new PersonDirector("Thin", gThin, p); 7 pdThin.CreatePerson(); 8 9 Graphics gFat = pictureBox2.CreateGraphics(); 10 11 PersonDirector pdFat = new PersonDirector("Fat", gFat, p); 12 pdFat.CreatePerson(); 13 }
注:文中所有代码及知识点均来自于《大话设计模式》,本人属于边学边看边敲代码边总结的阶段。
作者:可达鸭要进化
出处:http://www.cnblogs.com/Aries-rong/
本文版权归作者和博客园共有,欢迎转载,但是未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。