zoukankan      html  css  js  c++  java
  • 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     }
    View Code

     效果截图:

    题目延伸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     }
    View Code

    主函数:

     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         }
    View Code

    题目延伸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     }
    View Code

    解析:

    这里用到的就是建造者模式(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     }
    View Code

    主函数:

     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         }
    View Code

    注:文中所有代码及知识点均来自于《大话设计模式》,本人属于边学边看边敲代码边总结的阶段。

  • 相关阅读:
    那些年读过的书《Java并发编程实战》和《Java并发编程的艺术》三、任务执行框架—Executor框架小结
    那些年读过的书《Java并发编程实战》二、如何设计线程安全类
    那些年读过的书《Java并发编程实战》一、构建线程安全类和并发应用程序的基础
    重读《深入理解Java虚拟机》七、探究Java内存模型
    重读《深入理解Java虚拟机》六、Java泛型 VS C#泛型 (伪泛型 VS 真泛型)
    重读《深入理解Java虚拟机》五、虚拟机如何执行字节码?程序方法如何被执行?虚拟机执行引擎的工作机制
    重读《深入理解Java虚拟机》四、虚拟机如何加载Class文件
    input 文本框禁止输入表情
    win7右下角无线网图标显示未连接,但是实际上已连接上,也能上网
    history.back(-1)和history.go(-1)的区别
  • 原文地址:https://www.cnblogs.com/Aries-rong/p/7647666.html
Copyright © 2011-2022 走看看