.NET设计模式(4):建造者模式(Builder Pattern)

简介:

建造者模式(Builder Pattern

——.NET设计模式系列之四
Terrylee 2005 12 17
概述
在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法确相对稳定。如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?这就是要说的建造者模式。
本文通过现实生活中的买 KFC 的例子,用图解的方式来诠释建造者模式。
意图
将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
模型图
生活中的例子
生成器模式将复杂对象的构建与对象的表现分离开来,这样使得同样的构建过程可以创建出不同的表现。这种模式用于快餐店制作儿童餐。典型的儿童餐包括一个主食,一个辅食,一杯饮料和一个玩具(例如汉堡、炸鸡、可乐和玩具车)。这些在不同的儿童餐中可以是不同的,但是组合成儿童餐的过程是相同的。无论顾客点的是汉堡,三名治还是鸡肉,过程都是一样的。柜台的员工直接把主食,辅食和玩具放在一起。这些是放在一个袋子中的。饮料被倒入杯中,放在袋子外边。这些过程在相互竞争的餐馆中是同样的。
实现过程图解
在这里我们还是以去 KFC 店买套餐为例子,示意图如下:
客户端:顾客。想去买一套套餐(这里面包括汉堡,可乐,薯条),可以有 1 号和 2 号两种套餐供顾客选择。
指导者角色:收银员。知道顾客想要买什么样的套餐,并告诉餐馆员工去准备套餐。
建造者角色:餐馆员工。按照收银员的要求去准备具体的套餐,分别放入汉堡,可乐,薯条等。
产品角色:最后的套餐,所有的东西放在同一个盘子里面。
下面开始我们的买套餐过程。
1 .客户创建 Derector 对象,并用它所想要的 Builder 对象进行配置。顾客进入 KFC 店要买套餐,先找到一个收银员,相当于创建了一个指导者对象。这位收银员给出两种套餐供顾客选择: 1 普通套餐, 2 黄金套餐。完成的工作如时序图中红色部分所示。
程序实现:
 1 None.gif using  System;
 2 None.gif using  System.Configuration;
 3 None.gif using  System.Reflection;
 4 None.gif
 5 None.gif namespace  KFC
 6 ExpandedBlockStart.gif {
 7ExpandedSubBlockStart.gif    /// <summary>
 8InBlock.gif    /// Client 类
 9ExpandedSubBlockEnd.gif    /// </summary>

10InBlock.gif    public class Client
11ExpandedSubBlockStart.gif    {
12InBlock.gif        public static void Main(string[] args)
13ExpandedSubBlockStart.gif        {
14InBlock.gif            FoodManager foodmanager = new FoodManager();
15InBlock.gif
16InBlock.gif            Builder instance;
17InBlock.gif
18InBlock.gif            Console.WriteLine("Please Enter Food No:");
19InBlock.gif
20InBlock.gif            string No = Console.ReadLine();
21InBlock.gif
22InBlock.gif            string foodType = ConfigurationSettings.AppSettings["No"+No];
23InBlock.gif
24InBlock.gif            instance = (Builder)Assembly.Load("KFC").CreateInstance("KFC." + foodType);
25InBlock.gif
26InBlock.gif            foodmanager.Construct(instance);
27ExpandedSubBlockEnd.gif        }

28ExpandedSubBlockEnd.gif    }

29ExpandedBlockEnd.gif}

30 None.gif

产品(套餐)类:
 1 None.gif using  System;
 2 None.gif using  System.Collections;
 3 None.gif
 4 None.gif namespace  KFC
 5 ExpandedBlockStart.gif {
 6ExpandedSubBlockStart.gif    /// <summary>
 7InBlock.gif    /// Food类,即产品类
 8ExpandedSubBlockEnd.gif    /// </summary>

 9InBlock.gif    public class Food
10ExpandedSubBlockStart.gif    {
11InBlock.gif        Hashtable food = new Hashtable();
12InBlock.gif        
13ExpandedSubBlockStart.gif        /// <summary>
14InBlock.gif        /// 添加食品
15InBlock.gif        /// </summary>
16InBlock.gif        /// <param name="strName">食品名称</param>
17ExpandedSubBlockEnd.gif        /// <param name="Price">价格</param>

18InBlock.gif        public void Add(string strName,string Price)
19ExpandedSubBlockStart.gif        {
20InBlock.gif            food.Add(strName,Price);
21ExpandedSubBlockEnd.gif        }

22InBlock.gif        
23ExpandedSubBlockStart.gif        /// <summary>
24InBlock.gif        /// 显示食品清单
25ExpandedSubBlockEnd.gif        /// </summary>

26InBlock.gif        public void Show()
27ExpandedSubBlockStart.gif        {
28InBlock.gif            IDictionaryEnumerator myEnumerator  = food.GetEnumerator();
29InBlock.gif            Console.WriteLine("Food List:");
30InBlock.gif            Console.WriteLine("------------------------------");
31InBlock.gif            string strfoodlist = "";
32InBlock.gif            while(myEnumerator.MoveNext())
33ExpandedSubBlockStart.gif            {
34InBlock.gif                strfoodlist = strfoodlist + "\n\n" + myEnumerator.Key.ToString();
35InBlock.gif                strfoodlist = strfoodlist + ":\t" +myEnumerator.Value.ToString();
36ExpandedSubBlockEnd.gif            }

37InBlock.gif            Console.WriteLine(strfoodlist);
38InBlock.gif            Console.WriteLine("\n------------------------------");
39ExpandedSubBlockEnd.gif        }

40ExpandedSubBlockEnd.gif    }

41ExpandedBlockEnd.gif}

42 None.gif
2 .指导者通知建造器。收银员(指导者)告知餐馆员工准备套餐。这里我们准备套餐的顺序是:放入汉堡,可乐倒入杯中,薯条放入盒中,并把这些东西都放在盘子上。这个过程对于普通套餐和黄金套餐来说都是一样的,不同的是它们的汉堡,可乐,薯条价格不同而已。如时序图红色部分所示:
程序实现:
 1 None.gif using  System;
 2 None.gif
 3 None.gif namespace  KFC
 4 ExpandedBlockStart.gif {
 5ExpandedSubBlockStart.gif    /// <summary>
 6InBlock.gif    /// FoodManager类,即指导者
 7ExpandedSubBlockEnd.gif    /// </summary>

 8InBlock.gif    public class FoodManager
 9ExpandedSubBlockStart.gif    {
10InBlock.gif        public void Construct(Builder builder)
11ExpandedSubBlockStart.gif        {
12InBlock.gif            builder.BuildHamb();
13InBlock.gif
14InBlock.gif            builder.BuildCoke();
15InBlock.gif
16InBlock.gif            builder.BuildChip();
17ExpandedSubBlockEnd.gif        }
    
18ExpandedSubBlockEnd.gif    }

19ExpandedBlockEnd.gif}

20 None.gif
3 .建造者处理指导者的要求,并将部件添加到产品中。餐馆员工(建造者)按照收银员要求的把对应的汉堡,可乐,薯条放入盘子中。这部分是建造者模式里面富于变化的部分,因为顾客选择的套餐不同,套餐的组装过程也不同,这步完成产品对象的创建工作。
程序实现:
 1 None.gif using  System;
 2 None.gif
 3 None.gif namespace  KFC
 4 ExpandedBlockStart.gif {
 5ExpandedSubBlockStart.gif    /// <summary>
 6InBlock.gif    /// Builder类,即抽象建造者类,构造套餐
 7ExpandedSubBlockEnd.gif    /// </summary>

 8InBlock.gif    public abstract class Builder
 9ExpandedSubBlockStart.gif    {    
10ExpandedSubBlockStart.gif        /// <summary>
11InBlock.gif        /// 添加汉堡
12ExpandedSubBlockEnd.gif        /// </summary>

13InBlock.gif        public abstract void BuildHamb();
14InBlock.gif        
15ExpandedSubBlockStart.gif        /// <summary>
16InBlock.gif        /// 添加可乐
17ExpandedSubBlockEnd.gif        /// </summary>

18InBlock.gif        public abstract void BuildCoke();
19InBlock.gif        
20ExpandedSubBlockStart.gif        /// <summary>
21InBlock.gif        /// 添加薯条
22ExpandedSubBlockEnd.gif        /// </summary>

23InBlock.gif        public abstract void BuildChip();
24InBlock.gif        
25ExpandedSubBlockStart.gif        /// <summary>
26InBlock.gif        /// 返回结果
27InBlock.gif        /// </summary>
28ExpandedSubBlockEnd.gif        /// <returns>食品对象</returns>

29InBlock.gif        public abstract Food GetFood();
30ExpandedSubBlockEnd.gif    }

31ExpandedBlockEnd.gif}

32 None.gif

 1 None.gif using  System;
 2 None.gif
 3 None.gif namespace  KFC
 4 ExpandedBlockStart.gif {
 5ExpandedSubBlockStart.gif    /// <summary>
 6InBlock.gif    /// NormalBuilder类,具体构造者,普通套餐
 7ExpandedSubBlockEnd.gif    /// </summary>

 8InBlock.gif    public class NormalBuilder:Builder
 9ExpandedSubBlockStart.gif    {
10InBlock.gif        private Food NormalFood = new Food();
11InBlock.gif
12InBlock.gif        public override void BuildHamb()
13ExpandedSubBlockStart.gif        {
14InBlock.gif            NormalFood.Add("NormalHamb","¥10.50");
15ExpandedSubBlockEnd.gif        }

16InBlock.gif        
17InBlock.gif        public override void BuildCoke()
18ExpandedSubBlockStart.gif        {
19InBlock.gif            NormalFood.Add("CokeCole","¥4.50");
20ExpandedSubBlockEnd.gif        }

21InBlock.gif
22InBlock.gif        public override void BuildChip()
23ExpandedSubBlockStart.gif        {
24InBlock.gif            NormalFood.Add("FireChips","¥2.00");
25ExpandedSubBlockEnd.gif        }

26InBlock.gif
27InBlock.gif        public override Food GetFood()
28ExpandedSubBlockStart.gif        {
29InBlock.gif            return NormalFood;
30ExpandedSubBlockEnd.gif        }

31InBlock.gif
32ExpandedSubBlockEnd.gif    }

33ExpandedBlockEnd.gif}

34 None.gif

 1 None.gif using  System;
 2 None.gif
 3 None.gif namespace  KFC
 4 ExpandedBlockStart.gif {
 5ExpandedSubBlockStart.gif    /// <summary>
 6InBlock.gif    /// GoldBuilder类,具体构造者,黄金套餐
 7ExpandedSubBlockEnd.gif    /// </summary>

 8InBlock.gif    public class GoldBuilder:Builder
 9ExpandedSubBlockStart.gif    {
10InBlock.gif        private Food GoldFood = new Food();
11InBlock.gif
12InBlock.gif        public override void BuildHamb()
13ExpandedSubBlockStart.gif        {
14InBlock.gif            GoldFood.Add("GoldHamb","¥13.50");
15ExpandedSubBlockEnd.gif        }

16InBlock.gif        
17InBlock.gif        public override void BuildCoke()
18ExpandedSubBlockStart.gif        {
19InBlock.gif            GoldFood.Add("CokeCole","¥4.50");
20ExpandedSubBlockEnd.gif        }

21InBlock.gif
22InBlock.gif        public override void BuildChip()
23ExpandedSubBlockStart.gif        {
24InBlock.gif            GoldFood.Add("FireChips","¥3.50");
25ExpandedSubBlockEnd.gif        }

26InBlock.gif
27InBlock.gif        public override Food GetFood()
28ExpandedSubBlockStart.gif        {
29InBlock.gif            return GoldFood;
30ExpandedSubBlockEnd.gif        }

31InBlock.gif
32ExpandedSubBlockEnd.gif    }

33ExpandedBlockEnd.gif}

34 None.gif

4 .客户从建造者检索产品。从餐馆员工准备好套餐后,顾客再从餐馆员工那儿拿回套餐。这步客户程序要做的仅仅是取回已经生成的产品对象,如时序图中红色部分所示。
完整的客户程序:
 1 None.gif using  System;
 2 None.gif using  System.Configuration;
 3 None.gif using  System.Reflection;
 4 None.gif
 5 None.gif namespace  KFC
 6 ExpandedBlockStart.gif {
 7ExpandedSubBlockStart.gif    /// <summary>
 8InBlock.gif    /// Client 类
 9ExpandedSubBlockEnd.gif    /// </summary>

10InBlock.gif    public class Client
11ExpandedSubBlockStart.gif    {
12InBlock.gif        public static void Main(string[] args)
13ExpandedSubBlockStart.gif        {
14InBlock.gif            FoodManager foodmanager = new FoodManager();
15InBlock.gif
16InBlock.gif            Builder instance;
17InBlock.gif
18InBlock.gif            Console.WriteLine("Please Enter Food No:");
19InBlock.gif
20InBlock.gif            string No = Console.ReadLine();
21InBlock.gif
22InBlock.gif            string foodType = ConfigurationSettings.AppSettings["No"+No];
23InBlock.gif
24InBlock.gif            instance = (Builder)Assembly.Load("KFC").CreateInstance("KFC." + foodType);
25InBlock.gif
26InBlock.gif            foodmanager.Construct(instance);
27InBlock.gif
28InBlock.gif            Food food = instance.GetFood();
29InBlock.gif            food.Show();
30InBlock.gif
31InBlock.gif            Console.ReadLine();
32ExpandedSubBlockEnd.gif        }

33ExpandedSubBlockEnd.gif    }

34ExpandedBlockEnd.gif}

35 None.gif
通过分析不难看出,在这个例子中,在准备套餐的过程是稳定的,即按照一定的步骤去做,而套餐的组成部分则是变化的,有可能是普通套餐或黄金套餐等。这个变化就是建造者模式中的“变化点“,就是我们要封装的部分。
另外一个例子
在这里我们再给出另外一个关于建造房子的例子。客户程序通过调用 指导者  (CDirector class) BuildHouse() 方法来创建一个房子。该方法有一个布尔型的参数 blnBackyard ,当 blnBackyard 为假时指导者将创建一个 Apartment Concrete Builder ),当它为真时将创建一个 Single Family Home Concrete Builder )。这两种房子都实现了接口 Ihouse
程序实现:
  1 None.gif // 关于建造房屋的例子
  2 None.gif using  System;
  3 None.gif using  System.Collections;
  4 None.gif
  5 ExpandedBlockStart.gif /// <summary>
  6InBlock.gif/// 抽象建造者
  7ExpandedBlockEnd.gif/// </summary>

  8 None.gif public   interface  IHouse
  9 ExpandedBlockStart.gif {
 10InBlock.gif    bool GetBackyard();
 11InBlock.gif    long NoOfRooms();
 12InBlock.gif    string  Description();
 13ExpandedBlockEnd.gif}

 14 None.gif
 15 ExpandedBlockStart.gif /// <summary>
 16InBlock.gif/// 具体建造者
 17ExpandedBlockEnd.gif/// </summary>

 18 None.gif public   class  CApt:IHouse
 19 ExpandedBlockStart.gif {
 20InBlock.gif    private bool mblnBackyard;
 21InBlock.gif    private Hashtable Rooms;
 22InBlock.gif    public CApt()
 23ExpandedSubBlockStart.gif    {
 24InBlock.gif        CRoom room;    
 25InBlock.gif        Rooms = new Hashtable();
 26InBlock.gif        room = new CRoom();
 27InBlock.gif        room.RoomName = "Master Bedroom";
 28InBlock.gif        Rooms.Add ("room1",room);
 29InBlock.gif
 30InBlock.gif        room = new CRoom();
 31InBlock.gif        room.RoomName = "Second Bedroom";
 32InBlock.gif        Rooms.Add ("room2",room);
 33InBlock.gif
 34InBlock.gif        room = new CRoom();
 35InBlock.gif        room.RoomName = "Living Room";
 36InBlock.gif        Rooms.Add ("room3",room);
 37InBlock.gif        
 38InBlock.gif        mblnBackyard = false;
 39ExpandedSubBlockEnd.gif    }

 40InBlock.gif
 41InBlock.gif    public bool GetBackyard()
 42ExpandedSubBlockStart.gif    {
 43InBlock.gif        return mblnBackyard;
 44ExpandedSubBlockEnd.gif    }

 45InBlock.gif    public long NoOfRooms()
 46ExpandedSubBlockStart.gif    {
 47InBlock.gif        return Rooms.Count; 
 48ExpandedSubBlockEnd.gif    }

 49InBlock.gif    public string  Description()
 50ExpandedSubBlockStart.gif    {
 51InBlock.gif        IDictionaryEnumerator myEnumerator  = Rooms.GetEnumerator();
 52InBlock.gif        string strDescription;
 53InBlock.gif        strDescription = "This is an Apartment with " + Rooms.Count + " Rooms \n";
 54InBlock.gif        strDescription = strDescription + "This Apartment doesn't have a backyard \n";                        
 55InBlock.gif        while (myEnumerator.MoveNext())
 56ExpandedSubBlockStart.gif        {
 57InBlock.gif            strDescription = strDescription + "\n" + myEnumerator.Key + "\t" + ((CRoom)myEnumerator.Value).RoomName;
 58ExpandedSubBlockEnd.gif        }

 59InBlock.gif        return strDescription;
 60ExpandedSubBlockEnd.gif    }

 61ExpandedBlockEnd.gif}

 62 None.gif
 63 ExpandedBlockStart.gif /// <summary>
 64InBlock.gif/// 具体建造者
 65ExpandedBlockEnd.gif/// </summary>

 66 None.gif public   class  CSFH:IHouse
 67 ExpandedBlockStart.gif {
 68InBlock.gif    private bool mblnBackyard;
 69InBlock.gif    private Hashtable Rooms;
 70InBlock.gif    public CSFH()
 71ExpandedSubBlockStart.gif    {
 72InBlock.gif        CRoom room;
 73InBlock.gif        Rooms = new Hashtable();
 74InBlock.gif
 75InBlock.gif        room = new CRoom();
 76InBlock.gif        room.RoomName = "Master Bedroom";
 77InBlock.gif        Rooms.Add ("room1",room);
 78InBlock.gif
 79InBlock.gif        room = new CRoom();
 80InBlock.gif        room.RoomName = "Second Bedroom";
 81InBlock.gif        Rooms.Add ("room2",room);
 82InBlock.gif
 83InBlock.gif        room = new CRoom();
 84InBlock.gif        room.RoomName = "Third Room";
 85InBlock.gif        Rooms.Add ("room3",room);
 86InBlock.gif        
 87InBlock.gif        room = new CRoom();
 88InBlock.gif        room.RoomName = "Living Room";
 89InBlock.gif        Rooms.Add ("room4",room);
 90InBlock.gif
 91InBlock.gif        room = new CRoom();
 92InBlock.gif        room.RoomName = "Guest Room";
 93InBlock.gif        Rooms.Add ("room5",room);
 94InBlock.gif
 95InBlock.gif        mblnBackyard = true;
 96InBlock.gif 
 97ExpandedSubBlockEnd.gif    }

 98InBlock.gif
 99InBlock.gif    public bool GetBackyard()
100ExpandedSubBlockStart.gif    {
101InBlock.gif        return mblnBackyard;
102ExpandedSubBlockEnd.gif    }

103InBlock.gif    public long NoOfRooms()
104ExpandedSubBlockStart.gif    {
105InBlock.gif        return Rooms.Count;
106ExpandedSubBlockEnd.gif    }

107InBlock.gif    public string  Description()
108ExpandedSubBlockStart.gif    {
109InBlock.gif        IDictionaryEnumerator myEnumerator  = Rooms.GetEnumerator();
110InBlock.gif        string strDescription;
111InBlock.gif        strDescription = "This is an Single Family Home with " + Rooms.Count + " Rooms \n";
112InBlock.gif        strDescription = strDescription + "This house has a backyard \n"
113InBlock.gif        while (myEnumerator.MoveNext())
114ExpandedSubBlockStart.gif        {
115InBlock.gif            strDescription = strDescription + "\n" + myEnumerator.Key + "\t" + ((CRoom)myEnumerator.Value).RoomName; 
116ExpandedSubBlockEnd.gif        }
      
117InBlock.gif        return strDescription;
118ExpandedSubBlockEnd.gif    }

119ExpandedBlockEnd.gif}

120 None.gif
121 None.gif public   interface  IRoom
122 ExpandedBlockStart.gif {
123ExpandedSubBlockStart.gif    string RoomName{get;set;}
124ExpandedBlockEnd.gif}

125 None.gif
126 None.gif public   class  CRoom:IRoom
127 ExpandedBlockStart.gif {
128InBlock.gif    private string mstrRoomName;
129InBlock.gif    public string RoomName
130ExpandedSubBlockStart.gif    {
131InBlock.gif        get
132ExpandedSubBlockStart.gif        {
133InBlock.gif            return mstrRoomName;
134ExpandedSubBlockEnd.gif        }

135InBlock.gif        set 
136ExpandedSubBlockStart.gif        {
137InBlock.gif            mstrRoomName = value;
138ExpandedSubBlockEnd.gif        }

139ExpandedSubBlockEnd.gif    }

140ExpandedBlockEnd.gif}

141 None.gif
142 ExpandedBlockStart.gif /// <summary>
143InBlock.gif/// 指导者
144ExpandedBlockEnd.gif/// </summary>

145 None.gif public   class  CDirector
146 ExpandedBlockStart.gif {
147InBlock.gif    public IHouse BuildHouse(bool blnBackyard)
148ExpandedSubBlockStart.gif    {
149InBlock.gif        if (blnBackyard)
150ExpandedSubBlockStart.gif        {
151InBlock.gif            return new CSFH();
152ExpandedSubBlockEnd.gif        }

153InBlock.gif        else
154ExpandedSubBlockStart.gif        {
155InBlock.gif            return new CApt(); 
156ExpandedSubBlockEnd.gif        }

157ExpandedSubBlockEnd.gif    }

158ExpandedBlockEnd.gif}

159 None.gif
160 ExpandedBlockStart.gif /// <summary>
161InBlock.gif/// 客户程序
162ExpandedBlockEnd.gif/// </summary>

163 None.gif public   class  Client
164 ExpandedBlockStart.gif {
165InBlock.gif    static void Main(string[] args) 
166ExpandedSubBlockStart.gif    {
167InBlock.gif        CDirector objDirector = new CDirector();
168InBlock.gif        IHouse objHouse;
169InBlock.gif
170InBlock.gif        string Input = Console.ReadLine();
171InBlock.gif        objHouse = objDirector.BuildHouse(bool.Parse(Input));
172InBlock.gif    
173InBlock.gif        Console.WriteLine(objHouse.Description());
174InBlock.gif        Console.ReadLine();
175ExpandedSubBlockEnd.gif    }

176ExpandedBlockEnd.gif}

177 None.gif
178 None.gif
建造者模式的几种演化
省略抽象建造者角色
系统中只需要一个具体建造者,省略掉抽象建造者,结构图如下:
指导者代码如下:
 1 None.gif   class  Director
 2 ExpandedBlockStart.gif   {
 3InBlock.gif   private ConcreteBuilder builder;
 4InBlock.gif 
 5InBlock.gif   public void Construct()
 6ExpandedSubBlockStart.gif    {
 7InBlock.gif     builder.BuildPartA();
 8InBlock.gif     builder.BuildPartB();
 9ExpandedSubBlockEnd.gif   }

10ExpandedBlockEnd.gif }
省略指导者角色
抽象建造者角色已经被省略掉,还可以省略掉指导者角色。让 Builder 角色自己扮演指导者与建造者双重角色。结构图如下:
建造者角色代码如下:
 1 None.gif   public   class  Builder
 2 ExpandedBlockStart.gif   {
 3InBlock.gif   private Product product = new Product();
 4InBlock.gif 
 5InBlock.gif   public void BuildPartA()
 6ExpandedSubBlockStart.gif    
 7InBlock.gif     //dot.gifdot.gif
 8ExpandedSubBlockEnd.gif   }

 9InBlock.gif 
10InBlock.gif   public void BuildPartB()
11ExpandedSubBlockStart.gif    {
12InBlock.gif     //dot.gifdot.gif
13ExpandedSubBlockEnd.gif   }

14InBlock.gif 
15InBlock.gif   public Product GetResult()
16ExpandedSubBlockStart.gif    {
17InBlock.gif     return product;
18ExpandedSubBlockEnd.gif   }

19InBlock.gif 
20InBlock.gif   public void Construct()
21ExpandedSubBlockStart.gif    {
22InBlock.gif     BuildPartA();
23InBlock.gif     BuildPartB();
24ExpandedSubBlockEnd.gif   }

25ExpandedBlockEnd.gif }

客户程序:
 1 None.gif   public   class  Client
 2 ExpandedBlockStart.gif   {
 3InBlock.gif   private static Builder builder;
 4InBlock.gif 
 5InBlock.gif   public static void Main()
 6ExpandedSubBlockStart.gif    {
 7InBlock.gif     builder = new Builder();
 8InBlock.gif     builder.Construct();
 9InBlock.gif     Product product = builder.GetResult();
10ExpandedSubBlockEnd.gif   }

11ExpandedBlockEnd.gif }

合并建造者角色和产品角色
建造模式失去抽象建造者角色和指导者角色后,可以进一步退化,从而失去具体建造者角色,此时具体建造者角色和产品角色合并,从而使得产品自己就是自己的建造者。这样做混淆了对象的建造者和对象本身,但是有时候一个产品对象有着固定的几个零件,而且永远只有这几个零件,此时将产品类和建造类合并,可以使系统简单易读。结构图如下:
实现要点
1 、建造者模式主要用于“分步骤构建一个复杂的对象”,在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。
2 产品不需要抽象类,特别是由于创建对象的算法复杂而导致使用此模式的情况下或者此模式应用于产品的生成过程,其最终结果可能差异很大,不大可能提炼出一个抽象产品类。
3
、创建者中的创建子部件的接口方法不是抽象方法而是空方法,不进行任何操作,具体的创建者只需要覆盖需要的方法就可以,但是这也不是绝对的,特别是类似文本转换这种情况下,缺省的方法将输入原封不动的输出是合理的缺省操作。
4 、前面我们说过的抽象工厂模式(Abtract Factory)解决“系列对象”的需求变化,Builder模式解决“对象部分”的需求变化,建造者模式常和组合模式(Composite Pattern)结合使用。
效果
1 、建造者模式的使用使得产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的细节。
2
、每一个 Builder 都相对独立,而与其它的 Builder 无关。
3
、可使对构造过程更加精细控制。
4 、将构建代码和表示代码分开。
5 、建造者模式的缺点在于难于应付“分步骤构建算法”的需求变动。
适用性
以下情况应当使用建造者模式:
1 、需要生成的产品对象有复杂的内部结构。
2
、需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3
  在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。
应用场景
1、    RTF 文档交换格式阅读器。
2、    .NET 环境下的字符串处理 StringBuilder ,这是一种简化了的建造者模式。
3、    ……
总结
建造者模式的实质是解耦组装过程和创建具体部件,使得我们不用去关心每个部件是如何组装的。
______________________________________________________________________________________
参考资料:
Java 与设计模式》阎宏  
《设计模式(中文版)》
DesignPatternsExplained










本文转自lihuijun51CTO博客,原文链接: http://blog.51cto.com/terrylee/67747  ,如需转载请自行联系原作者




相关文章
|
24天前
|
设计模式 Java
【设计模式系列笔记】建造者模式
建造者模式是一种创建型设计模式,用于将复杂对象的构建与其表示分离,使构建过程可定制。关键元素包括产品类(定义要构建的对象)、建造者接口(定义构建方法)、具体建造者类(实现构建过程)和指导者类(负责构建过程)。通过建造者模式,客户端可以灵活地创建具有不同表示的复杂对象,提高代码的可读性和可维护性,尤其适用于构建过程复杂且包含多个可选部分的情况。
108 1
|
4月前
|
设计模式 Java 机器人
Java设计模式-建造者模式
建造者(Builder)模式指将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。它是把对象的构建和表述分离。
52 0
Java设计模式-建造者模式
|
4月前
|
设计模式
设计模式 | 建造者模式
设计模式 | 建造者模式
37 0
|
4月前
|
设计模式 算法 Java
行为型设计模式-策略模式(Strategy Pattern)
行为型设计模式-策略模式(Strategy Pattern)
|
4月前
|
设计模式 Go 开发工具
Golang设计模式——04建造者模式
Golang设计模式——04建造者模式
25 0
|
4月前
|
设计模式 算法
设计模式 - 行为型模式_ 访问者模式Visitor Pattern
设计模式 - 行为型模式_ 访问者模式Visitor Pattern
43 1
设计模式 - 行为型模式_ 访问者模式Visitor Pattern
|
设计模式 Java 应用服务中间件
设计模式 -结构型模式_门面模式(外观模式) Facade Pattern 在开源软件中的应用
设计模式 -结构型模式_门面模式(外观模式) Facade Pattern 在开源软件中的应用
37 1
|
4月前
|
设计模式 缓存 安全
设计模式 - 创建型模式_ 单例模式 Singleton Pattern
设计模式 - 创建型模式_ 单例模式 Singleton Pattern
40 0
|
1月前
|
设计模式 存储 Java
Java设计模式:解释一下单例模式(Singleton Pattern)。
`Singleton Pattern`是Java中的创建型设计模式,确保类只有一个实例并提供全局访问点。它通过私有化构造函数,用静态方法返回唯一的实例。类内静态变量存储此实例,对外仅通过静态方法访问。
16 1
|
1月前
|
设计模式 Java
小谈设计模式(14)—建造者模式
小谈设计模式(14)—建造者模式