将一个复杂对象的构建和它的表示分离,使得同样的创建过程可以有不同的表示。
要组装一台电脑,它的组装过程基本是不变的,都可以由主板、CPU、内存等按照某个稳定方式组合而成。然而主板、CPU、内存等零件本身都是可能多变的。将内存等这种易变的零件与电脑的其他部件分离,实现解耦合,则可以轻松实现电脑不断升级。
适用性:1,当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
2,当构造的过程中必须允许被构造的对象有不同的表示时。
在创建 Product 时,先编写好各种配件的组合方式,而每种配件则是由 ConcreteBuilder 进行具体的提供,然后由 Director 将每种配件给与产品类。
①Builder:为创建一个 product对象的各个部件指定抽象接口;
②ConcreateBuilder
1>实现Builder的接口以构造和装配该产品的各个部件
2>定义并明确它所创建的表示
③Director:构造一个使用Builder接口的对象;
④Product:表示被构造的复杂对象。ConcreateBuilder创建该产品的内部表示并定义它的装配过程。
在建造者模式中,Director规定了创建一个对象所需要的步骤和次序,builder则提供了一些完成这些步骤的方法,ConcreateBuilder给出了这些方法的具有实现,是对象的直接创建者。
- Builder 1,为创建一个Product对象的各个部件指定抽象接口
- ConcreteBuilder 1, 实现Builder的接口以构造和装配该产品的各个部件 2,定义并明确它所创建的表示 3, 提供一个检索产品的接口
- Director 1, 构造一个使用Builder接口的对象
- Product 1,表示被构造的的复杂对象,ConcreteBuilder创建该产品的内部表示并定义它的装配过程。 2,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
例子:游戏软件公司开发一款基于角色扮演的多人在线网络游戏,玩家可以再游戏中扮演虚拟世界中的特定角色,角色根据不同的游戏情节和统计数据(例如:力量,魔法,技能等)具有不同的能力,角色也会随着不断升级而拥有更加强大的能力。
首先我们明确我们需要制造产生的复杂产品 Product
1 //游戏中角色类,充当复杂产品对象 2 3 classActor 4 5 { 6 7 privatestringtype;//角色类型 8 9 privatestringsex;//性别 10 11 privatestringface;//面容 12 13 privatestringcostume;//服装 14 15 privatestringhairstyle;//发型 16 17 18 19 publicstringType 20 21 { 22 23 get{ return type; } 24 25 set{ type = value; } 26 27 } 28 29 publicstringSex 30 31 { 32 33 get{ return sex; } 34 35 set{ sex = value; } 36 37 } 38 39 publicstringFace 40 41 { 42 43 get{ return face; } 44 45 set{ face = value; } 46 47 } 48 49 publicstringCostume 50 51 { 52 53 get{ return costume; } 54 55 set{ costume = value; } 56 57 } 58 59 publicstringHairstyle 60 61 { 62 63 get{ return hairstyle; } 64 65 set{ hairstyle = value; } 66 67 } 68 69 }
对于这样一个复杂产品,我们抽象出一个建造者 Builder
1 //角色建造者:抽象建造者 2 3 abstractclassActorBuilder 4 5 { 6 7 protectedActor actor =new Actor(); 8 9 10 11 publicabstractvoidBuildType(); 12 13 publicabstractvoidBuildSex(); 14 15 publicabstractvoidBuildFace(); 16 17 publicabstractvoidBuildCostum(); 18 19 publicabstractvoidBuildHairstyle(); 20 21 22 23 //工厂方法、返回一个完整的游戏角色对象 24 25 publicActor CreateActor() 26 27 { 28 29 returnactor; 30 31 } 32 33 }
接下来我们实现Builder类,具体的建造者 ConcreteBuilder
英雄角色建造者
1 //英雄角色建造者,为具体建造者 2 3 classHeroBuilder:ActorBuilder 4 5 { 6 7 publicoverridevoidBuildType() 8 9 { 10 11 actor.Type = "英雄"; 12 13 } 14 15 publicoverridevoidBuildSex() 16 17 { 18 19 actor.Sex = "男"; 20 21 } 22 23 publicoverridevoidBuildFace() 24 25 { 26 27 actor.Face = "英俊"; 28 29 } 30 31 publicoverridevoidBuildCostume() 32 33 { 34 35 actor.Costume = "盔甲"; 36 37 } 38 39 publicoverridevoidBuildHairstyle() 40 41 { 42 43 actor.Hairstyle = "飘逸"; 44 45 } 46 47 }
天使角色建造者
1 //具体建造者:天使角色 2 3 classAngelBuilder:ActorBuilder 4 5 { 6 7 publicoverridevoidBuildType() 8 9 { 10 11 actor.Type = "天使"; 12 13 } 14 15 publicoverridevoidBuildSex() 16 17 { 18 19 actor.Sex = "女"; 20 21 } 22 23 publicoverridevoidBuildFace() 24 25 { 26 27 actor.Face = "漂亮"; 28 29 } 30 31 publicoverridevoidBuildCostume() 32 33 { 34 35 actor.Costume = "白裙"; 36 37 } 38 39 publicoverridevoidBuildHairstyle() 40 41 { 42 43 actor.Hairstyle = "披肩长发"; 44 45 } 46 47 }
最后我们实现角色控制者 Director
1 //角色控制者:指挥者 2 3 classActorController 4 5 { 6 7 //逐步构建复杂产品对象 8 9 publicActor Construct(ActorBuilder ab) 10 11 { 12 13 Actor actor; 14 15 ab.BuildType(); 16 17 ab.BuildSex(); 18 19 ab.BuildFace(); 20 21 ab.BuildCostume(); 22 23 ab.BuildHairstyle(); 24 25 actor = ab.CreateActor(); 26 27 returnactor; 28 29 } 30 31 }
配置文件:App.config的设置(可以设置所需创建的对象)
1 <?xmlversion="1.0"encoding="utf-8"?> 2 3 <configuration> 4 5 <startup> 6 7 <supportedRuntimeversion="v4.0"sku=".NETFramework,Version=v4.5.2,Profile=Client"/> 8 9 </startup> 10 11 <appSettings> 12 13 <addkey="builder"value="BuilderSample.AngelBuilder"/> 14 15 </appSettings> 16 17 </configuration>
客户端的测试
1 classProgram 2 3 { 4 5 staticvoidMain(string[] args) 6 7 { 8 9 //抽象建造者对象 10 11 ActorBuilder ab; 12 13 //读取配置文件,获取要创建的角色的类型 14 15 stringbuilderType = ConfigurationManager.AppSettings["builder"]; 16 17 //反射生成对象 18 19 ab = (ActorBuilder)Assembly.Load("BuilderSample").CreateInstance(builderType); 20 21 ActorController ac =new ActorController(); 22 23 Actor actor; 24 25 //指挥者创建完整的建造对象 26 27 actor = ac.Construct(ab); 28 29 30 31 Console.WriteLine("{0}的外观",actor.Type); 32 33 Console.WriteLine("性别{0}",actor.Sex); 34 35 Console.WriteLine("面容{0}",actor.Face); 36 37 Console.WriteLine("服装{0}",actor.Costume); 38 39 Console.WriteLine("发型{0}",actor.Hairstyle); 40 41 Console.Read(); 42 43 } 44 45 }
四、建造者的优点
1)客户端不必知道产品的内部结构;
2)每一个建造者相对比较独立,便于增加建造者对象;
3)用户可以控制创建过程。
五、建造者模式的确定
1)产品具有较多的共同点,组成部分相似,如果对象之间差异较大就不适合该模式;
2)如果产品复杂,且对象较多,则系统会变的庞大。