设计模式- 建造者模式

  其实有很多设计模式并没有像网上一些文章那样写的很复杂,理解了一下后发现他的实现原理很清晰。比如建造者设计模式。

  建造者设计模式又叫生成器模式,我们不要叫他生成器模式,我觉的这个名字不好听。我比较喜欢建造者设计模式这个名字。

 

  先来了解一下建造者设计模式是什么?

  假设你是一个帮别人组装电脑主机的人,那么可以说,这时你就是当建造者设计模式指挥者这么一个角色。试想一下你要怎么样帮客户组装一台主机?装主机的人一般会先确定客户需要的主机配置,例如客户要求主板用华硕的,内存用金斯顿的,硬盘用西部数据的,CPU用因特的,电源用航嘉的,机箱用长城的……,先确定好后,再进行组装主机。

  作为装主机的人(指挥者),你根据客户提供的配置去装主机。但装主机时,先装主板还是先装硬盘,完全由你决定。具体装的过程,内部实现细节,客户不必去关心。对于客户而言他们只是需要提供他们所需要的主机配置清单而以。

   那么对于装主机的人,他是这个设计模式里唯一的,不变的部份,所有的客户都是找他装,所以在C#里可以把装主机的人写成一个单独的类,他的工作就是接收不同客户传递过来给他配置清单进行组装主机。

  而变化的部份是不同的主机配置清单,那么我们可以变化的这部份写一个抽象类,例如如下代码:

    public abstract class ComputerBuilder
    {
           public abstract void MainBoard();//主板
        public abstract void CPU();//CPU
           public abstract void Memory();//内存
        public abstract void HardDisk();//硬盘
        public abstract void PowerSupply();//电源
    }

  接着由不同的客户实现不同的抽象类:

   //客户A需要实现的主机配置
    public class CustomerA : ComputerBuilder
    {
        public override void CPU()
        {
            Console.WriteLine("AMD2代");
        }

        public override void MainBoard()
        {
            Console.WriteLine("华硕M4N68T-MLE");
        }

        public override void HardDisk()
        {
            Console.WriteLine("西部数据500G");
        }

        public override void Memory()

        {
            Console.WriteLine("金斯顿2G");
        }

        public override void PowerSupply()
        {
            Console.WriteLine("技展450w ");
        }
    }

    //客户B需要实现的主机配置
    public class CustomerB : ComputerBuilder
    {
        public override void CPU()
        {
            Console.WriteLine("AMD Athlon64 X2 3800+ AM2");
        }

        public override void MainBoard()
        {
            Console.WriteLine("华硕 M2V");
        }

        public override void HardDisk()
        {
            Console.WriteLine("希捷 160G");
        }

        public override void Memory()
        {
            Console.WriteLine("威刚VDATA 1GB DDRII667");
        }

        public override void PowerSupply()
        {
            Console.WriteLine("Tt XP355(W3006)");
        }
    }

 

从这个例子我们看出在建造者设计模式有哪些东西,要抽象实现的方法(也就是装主机的人需要的配置,一个一个的配置可以当作一个一个的方法)。和一个建设者类(也就是装主机的人),里面有一个指挥者方法(Director)。

 

 

 

那么建造者设计模式可以应用在哪些场合?

在《大话设计模式》里面是这么说的:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示意图。这时候就用到了建造者模式。

读这句话的时候,我也不知道他在讲什么。但是看了里面给的代码,把思路搞清楚后再回过头来看这句,就看懂了。

 

还是以上面的组装电脑主机的例子来解释一下《大话设计模式》里的这句话。组装电脑的人,他组装电脑先后顺序已经做习惯了,这个过程不会改后,而且组装电脑需要的东西主板、内存、硬盘、CPU、电源这些是不会变的,但是他们的所需要的型号或者大小会变,例如客户不是要1G金斯顿内存,他要2G金斯顿内存,客户可能不要250G大小的西部数据硬盘,他要500G的三星硬盘。这些可都是会变化的。所以大话设计模式里的这句使得同样的构建过程可以创建不同的表示意图”,意思就可以这么理解成配置的东西内存、主板、硬盘这些和组装电脑的过程这些都是确定的,可是配置的型号和大小的可能不同,例如可能是要2G的内存或者是4G的内存等等,所以我们可以根据一定的装机需求,不同的型号和大小就能组装出不同性能的主机来,也就是上面的创建不同的表示意图出来这句一个道理。

不知道这么说好不好理解!

 

好了,最后我们还是贴一下自己写的代码和大话设计模式那个例子的代码。另外我看了一个博客:http://www.cnblogs.com/lovecherry/ 他里面有篇 无废话C#设计模式之六:Builder。我的例子就是参看他后写的。

自己写的代码例子:

View Code
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 
  6 namespace 建造者模式_装主机
  7 {
  8     class Program
  9     {
 10         static void Main(string[] args)
 11         {
 12 
 13             ComputerDirector cd = null;
 14         
 15             CustomerA ca = new CustomerA();
 16             cd = new ComputerDirector(ca);
 17             cd.CreateComputer();
 18 
 19             CustomerB cb = new CustomerB();
 20             cd = new ComputerDirector(cb);
 21             cd.CreateComputer();
 22 
 23             Console.ReadLine();
 24         }
 25     }
 26 
 27     public class ComputerDirector
 28     {
 29         private ComputerBuilder cb;
 30         public ComputerDirector(ComputerBuilder cb)
 31         {
 32             this.cb = cb;
 33         }
 34 
 35         public void CreateComputer()
 36         {
 37             //开始装电脑,先装那个由装主机的指挥者决定
 38             cb.CPU();
 39             cb.MainBoard();
 40             cb.Memory();
 41             cb.PowerSupply();
 42             cb.HardDisk();
 43         }
 44     }
 45 
 46     public abstract class ComputerBuilder
 47     {
 48         public abstract void MainBoard();//主板
 49         public abstract void CPU();//CPU
 50         public abstract void Memory();//内存
 51         public abstract void HardDisk();//硬盘
 52         public abstract void PowerSupply();//电源
 53     }
 54 
 55     //客户A需要实现的主机配置
 56     public class CustomerA : ComputerBuilder
 57     {
 58         public override void CPU()
 59         {
 60             Console.WriteLine("AMD2代");
 61         }
 62 
 63         public override void MainBoard()
 64         {
 65             Console.WriteLine("华硕M4N68T-MLE");
 66         }
 67 
 68         public override void HardDisk()
 69         {
 70             Console.WriteLine("西部数据500G");
 71         }
 72 
 73         public override void Memory()
 74         {
 75             Console.WriteLine("金斯顿2G");
 76         }
 77 
 78         public override void PowerSupply()
 79         {
 80             Console.WriteLine("技展450w ");
 81         }
 82     }
 83 
 84     //客户B需要实现的主机配置
 85     public class CustomerB : ComputerBuilder
 86     {
 87         public override void CPU()
 88         {
 89             Console.WriteLine("AMD Athlon64 X2 3800+ AM2");
 90         }
 91 
 92         public override void MainBoard()
 93         {
 94             Console.WriteLine("华硕 M2V");
 95         }
 96 
 97         public override void HardDisk()
 98         {
 99             Console.WriteLine("希捷 160G");
100         }
101 
102         public override void Memory()
103         {
104             Console.WriteLine("威刚VDATA 1GB DDRII667");
105         }
106 
107         public override void PowerSupply()
108         {
109             Console.WriteLine("Tt XP355(W3006)");
110         }
111     }
112 }

  大话设计模式代码如下,画人的建造者模式的主要代码,写成一个PersonBuilder类:

View Code
  1 namespace 建造者模式
  2 {
  3     //指挥者
  4     class PersonDirector
  5     {
  6         private PersonBuilder pb;
  7         public PersonDirector(PersonBuilder pb)
  8         {
  9             this.pb = pb;
 10         }
 11 
 12         //要画的先后顺序
 13         public void CreatePerson()
 14         {
 15             pb.BuildHead();
 16             pb.BuildBody();
 17             pb.BuildArmLeft();
 18             pb.BuildArmRight();
 19             pb.BuildLegLeft();
 20             pb.BuildLegRight();
 21         }
 22     }
 23 
 24     //要实现的抽象方法
 25     abstract class PersonBuilder
 26     {
 27         public abstract void BuildHead();
 28         public abstract void BuildBody();
 29         public abstract void BuildArmLeft();
 30         public abstract void BuildArmRight();
 31         public abstract void BuildLegLeft();
 32         public abstract void BuildLegRight();
 33     }
 34 
 35     //实现抽象类,画一个瘦瘦的人
 36     class PersonThinBuilder : PersonBuilder
 37     {
 38         private Graphics g;
 39         private Pen p;
 40 
 41         public PersonThinBuilder(Graphics g, Pen p)
 42         {
 43             this.g = g;
 44             this.p = p;
 45         }
 46 
 47         public override void BuildHead()
 48         {
 49             g.DrawEllipse(p, 50, 20, 30, 30);
 50         }
 51 
 52         public override void BuildBody()
 53         {
 54             g.DrawRectangle(p, 60, 50, 10, 50);
 55         }
 56 
 57         public override void BuildArmLeft()
 58         {
 59             g.DrawLine(p, 60, 50, 40, 100);
 60         }
 61 
 62         public override void BuildArmRight()
 63         {
 64             g.DrawLine(p, 70, 50, 90, 100);
 65         }
 66 
 67         public override void BuildLegLeft()
 68         {
 69             g.DrawLine(p, 60, 100, 45, 150);
 70         }
 71 
 72         public override void BuildLegRight()
 73         {
 74             g.DrawLine(p, 70, 100, 85, 150);
 75         }
 76     }
 77 
 78     //实现抽象类,画一个胖胖的人
 79     class PersonFatBuilder : PersonBuilder
 80     {
 81         private Graphics g;
 82         private Pen p;
 83 
 84         public PersonFatBuilder(Graphics g, Pen p)
 85         {
 86             this.g = g;
 87             this.p = p;
 88         }
 89 
 90         public override void BuildHead()
 91         {
 92             g.DrawEllipse(p, 50, 20, 30, 30);
 93         }
 94 
 95         public override void BuildBody()
 96         {
 97             g.DrawEllipse(p, 45, 50, 40, 50);
 98         }
 99 
100         public override void BuildArmLeft()
101         {
102             g.DrawLine(p, 50, 50, 30, 100);
103         }
104 
105         public override void BuildArmRight()
106         {
107             g.DrawLine(p, 80, 50, 100, 100);
108         }
109 
110         public override void BuildLegLeft()
111         {
112             g.DrawLine(p, 60, 100, 45, 150);
113         }
114 
115         public override void BuildLegRight()
116         {
117             g.DrawLine(p, 70, 100, 85, 150);
118         }
119     }
120 }

  WinForm里面的代码:

View Code
 1         private void button1_Click(object sender, EventArgs e)
 2         {
 3             //画笔
 4             Pen p = new Pen(Color.Red);
 5 
 6             //画一个瘦人
 7             PersonThinBuilder ptb = new PersonThinBuilder(pictureBox1.CreateGraphics(), p);
 8             //将要准备好的画瘦人的"材料"传给指挥者,由指挥者画
 9             PersonDirector pdThin = new PersonDirector(ptb);
10             pdThin.CreatePerson();
11             
12             
13             //同理准备好一个胖人的"材料",让指挥者画
14             PersonFatBuilder pfb = new PersonFatBuilder(pictureBox2.CreateGraphics(), p);
15             PersonDirector pdFat = new PersonDirector(pfb);
16             pdFat.CreatePerson();
17 
18         }

 

posted @ 2012-08-26 15:19  春天又来了  阅读(1560)  评论(1编辑  收藏  举报