创建者模式学习心得
适用场景:
某个东西需要由其他的东西组合而成。
如中国移动的套餐,套餐A是由短信包1和长话包2组成的;套餐B是由短信包2和长话包3组成的。
适合应付这样的变化:如果套餐的数目不确定,并且里面的包的数目和类别也不确定。
比如中国移动的套餐随着时间的变化,需要不断变化,并且不断推出新的套餐品种。
本文的例子场景:
搭配衣服场景。
一个人要去找工作,首先要选择一个合适的套装(Suit)。
而套装又是由上衣(Jacket)、裤子(pants)和鞋子(Shoe)组成的。
他要根据不同的工作性质选择不同的衣服。
涉及对象:
1。需要穿衣服的人:Client
2。指导它穿哪套套装的对象:Director
3。A套装的构造者:ABuilder,B套装的构造者:BBuilder,C套装的构造者:CBuilder
和他们继承的接口:IBuilder
4。套装:Suit
5。上衣:Jacket、裤子:pants、鞋子:shoe
类的关系图:图1
具体实现方法:
1。Client的职责是选择一种套装。client需要输入他所选择的套装类型。
class Client
... {
static void Main(string[] args)
...{
//test BuilderPattern
Director director = new Director();
IBuilder builder;
Console.WriteLine("input your choice : A , B or C?");
string Signal = Console.ReadLine();
builder = director.ConstructSuit(Signal);
Suit suit=builder.GetSuit();
suit.Show();
Console.ReadLine();
}
}
2。Director的职责是找出可以创建该套装的“创建者”。
他是沟通Client的需求和“创建者”工作的一个中间环节。
public class Director
... {
public IBuilder ConstructSuit(string Signal)
...{
switch (Signal)
...{
case "A": ...{ return new ABuilder(); }
case "B": ...{ return new BBuilder(); }
case "C": ...{ return new CBuilder(); }
default: return null;
}
}
}
3。ABuilder、BBuilder、CBuilder均实现IBuilder的接口,
用来创建A种的Suit、B种Suit、C种Suit。
public interface IBuilder
... {
Suit GetSuit();
}
public class ABuilder : IBuilder
... {
public Suit GetSuit()
...{
Jacket jacketA = new Jacket("A");
Pants pantsA = new Pants("A");
Shoe shoeA = new Shoe("A");
Suit suitA = new Suit(jacketA, pantsA, shoeA);
return suitA;
}
}
public class BBuilder : IBuilder
... {
public Suit GetSuit()
...{
Jacket jacketB = new Jacket("B");
Pants pantsB = new Pants("B");
Shoe shoeB = new Shoe("B");
Suit suitB = new Suit(jacketB, pantsB, shoeB);
return suitB;
}
}
public class CBuilder : IBuilder
... {
public Suit GetSuit()
...{
Jacket jacketC = new Jacket("C");
Pants pantsC = new Pants("C");
Shoe shoeC = new Shoe("C");
Suit suitC = new Suit(jacketC, pantsC, shoeC);
return suitC;
}
}
4。套装类。他的职责是规范一个套装应该有的三个部分,并且根据这三个部分创建出套装
public class Suit
... {
Jacket theJacket;
Pants thePants;
Shoe theShoe;
public Suit(Jacket jacket, Pants pants, Shoe shoe)
...{
theJacket = jacket;
thePants = pants;
theShoe = shoe;
}
public void Show()
...{
theJacket.show();
thePants.Show();
theShoe.Show();
}
}
5。裤子、衣服和鞋子,均是最基本的构成,职责是通过传入的 参数构造出一个自己:
public class Jacket
... {
public string JacketType;
public Jacket(string jacketType)
...{
JacketType = jacketType;
}
public void show()
...{
Console.WriteLine("I'm " + JacketType + " jacket");
}
}
public class Pants
... {
public string PantsColor;
public Pants(string pantsColor)
...{
PantsColor = pantsColor;
}
public void Show()
...{
Console.WriteLine("I'm " + PantsColor + " color Pants");
}
}
public class Shoe
... {
public string ShoeSize;
public Shoe(string shoeSize)
...{
ShoeSize = shoeSize;
}
public void Show()
...{
Console.WriteLine("I'm Shoe of" + ShoeSize);
}
}
效果:
按照传统的思维,我们会这样处理这个问题:
创建一个Suit的父类,然后不断的继承它,从而创造出A、B、C三种套装。
client根据自己的需求,来选择实例化不同的套装。
但是这样有什么缺点呢?
1。使用创建者模式的时候,Client并不必知道Suit这个东西,它只面对Director,
它只需要知道到底是A、B还是C。他不用关心到底是Suit还是Coad,或者是其他什么东西。
如果说在构造套餐之外,有其他的需求是和A、B、C的选择相关的,就可以体现出创建者模式的优势。
比如,A表示“严肃”系列,适合应聘行政工作;B表示“休闲”系列,适合应聘美工。
Client在对Director作出A、B的选择后,除了获得了一个合适的Suit,还需要获得一份“面试指导”。
这时候Director就可以调用其他对象了
2。builder之间更加松耦合。相对于传统的方法,它和Suit的关系是“使用”,而不是“继承”。
3。构造的过程可以更加精细控制。比如说,某种Suit不需要shoe了,它只要有jacket和pants就可以了。
它可以先构造jacket,也可以先构造shoe。。。
4。构建代码和表现代码分离。构造是在Builder类里面实现的,而表现是由suit实现的。
这样实现了控制和表现的分离。
5。不同的suit只是不同jacket、pants和shoe的排列组合而已,从概念上说不是继承的关系。
补充说明:
和工厂模式的区别:
1。builer的重点是在不同的请求下,给出不同的排列组合。
Factory的重点是在不同的请求下,给出不同类的实例。
2。Builder不需要一个抽象的Suit。而用工厂就需要了。
附:用工厂实现这个需求的类图:图2
这样的场景比较适合使用工厂:一个人要选择面试的裤子:它如果选A就给Apants,选B就给Bpants。。。
代码的优化:
其中,Director可以采用映射生成一个实例
这样的话,Director中就不需要出现A、B的字眼了。
public class Director
... {
public IBuilder ConstructSuit(string Signal)
...{
//switch (Signal)
// {
// case "A": { return new ABuilder(); }
// case "B": { return new BBuilder(); }
// case "C": { return new CBuilder(); }
// default: return null;
// }
return (IBuilder)Assembly.Load("ConsoleApplication1").CreateInstance("BuilderPattern." + Signal + "Builder");
}
}
模式应用:
这个模式的应用范围非常广。这种类似于“套餐”的 都可以应用。
1。用户页面的定制。
2。自动生成网站系统中的页面布局。如果可以做成这样的话,那网站只需要一个页面 了
根据它的需求定制它的控件就可以了。
3。DataList的建造
4。用户订阅不同的信息,其实也是套餐。