设计模式实例之创建型模式(Singleton、Abstract Factory、Builder)讲解(2)
抽象工厂模式(Abstract Factory)
抽象工厂,按字面含义来理解,就是一个不存在的工厂,只是抽象出来的一个概念工厂,反应到代码中,可以理解为定义了固定操作接口的一个抽象类,这个类不完成任何事(特殊情况也可以完成某些生产操作),而是交由它的子类来进行实际的操作。
理解概念总是困难的,因此用比喻的方式总是容易让人理解,这里我举个例子来说明抽象工厂,在我们写代码的过程中,经常会牵扯到界面元素的变动,比如常见的什么Xp样式风格、Office2003风格、Vista风格等等,例子中,我以生成文本框、复选框为例,来说明抽象工厂模式。
不论什么风格,它们都是控件,因此都会有创建文本框及复选框的方法,这些方法就是工厂方法,代码如下:
{
public abstract TextBox CreateTextbox();
public abstract CheckBox CreateCheckbox();
}
class StandardControlFactory : ControlFactory
{
public StandardControlFactory() { }
public override TextBox CreateTextbox()
{
return new TextBox();
}
public override CheckBox CreateCheckbox()
{
return new CheckBox();
}
}
StandardControlFactory类是创建标准控件的一个实现工厂,同样我们要实现XP样式的文本框创建,则重新继承一下抽象工厂类即可,代码如下:
{
public XpControlFactory() { }
public override TextBox CreateTextbox()
{
TextBox tb = new TextBox();
//对tb对象进行XP样式修改
return tb;
}
public override CheckBox CreateCheckbox()
{
CheckBox ck = new CheckBox();
//对ck对象进行XP样式修改
return ck;
}
}
在客户端使用的时候,通过送入不同的实现工厂,即可实现对界面的修改,例如:
{
Panel p = new Panel();
p.Controls.Add(factory.CreateCheckbox());
p.Controls.Add(factory.CreateTextbox());
return p;
}
上面的代码中,要修改不同风格的控件,只需要送入不同的抽象工厂实例即可。
生成器(Builder)
生成器,顾名思义是负责生成内容的容器。先摘录一下书上对生成器的说明:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
初看这段话,还真有些迷糊,举个例子来说明下,现实中我们进行网络编程的时候,收到的数据包是不固定的,因此,并不知道何时能收到完整的数据包,因此,我们需要有一个过程来处理这些数据信息,而处理的过程并不适宜放在接收数据的程序模块处,因此,我们需要一个专门的类来处理这些数据包,并将其生成合适的数据包供第三方模块使用。而这个处理这些数据包的类就叫做生成器,负责将数据流生成实际需要的内容。
构建器代码示例如下(代码为了简单易读,数据流用字符串代替):
{
private StringBuilder sb = new StringBuilder();//临时数据对象
private Queue<string> strResult = new Queue<string>();//结果队列
public BuilderTest()
{
}
public void PubData(string data)
{
if (data == Environment.NewLine)//如果是换行表示接收完对象
{
strResult.Enqueue(sb.ToString());
sb = new StringBuilder();
}
sb.Append(data);
}
public string GetStringResult()//取得传送结果
{
return strResult.Count > 0 ? strResult.Dequeue() : null;
}
}
数据流调用关系如下图:
注:
上例中与书中所说略有不同,不能体现Builder的多步生产操作,而是将其多步生产合成为一个PutData函数了。
所谓的多步操作,举例来说生产一个布娃娃,可能需要布娃娃的头、身体、手和脚,而这四个部份都是分开提供的,因此Builder需要提供这四个部份进行加工,需要提供接收内容的操作方法,如:PutHead,PutBody,PubHand,PubFoot等,当都推入的部件符合一个布娃娃的生产条件则自动生成一个布娃娃。
如上图所示“ReceiverObject”在代码中扮演了内容提供者,BuilderTest则负责进行数据内容分析,组合成数据对象,“UserObject”则是最终使用用户。
此时再来理解一下书中说的那句定义:“将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。“复杂对象”在此例中,就是网络传送的对象“Result”,复杂对象的构建则是指BuilderTest的处理操作。如果将BuilderTest的工作放在UserObject对象中来完成,那么在需要传送新的对象的时候,必然导致UserObject对象的修改,可实际上UserObject关心的并不是传送的数据流,而是最终的传送结果(Result),因此Builder实际上要做的事,就是将数据生成为最终使用者想要的结果。
Builder与Abstract Factory的区别:
刚开始的时候,我也觉得Builder和Abstract Factory差不多,深入了解后才发觉,它们之间也是有区别的,虽然它们都是生成新对象给使用者,也可以创建复杂对象,不过Abstract Factory是立即生成新的对象,有实时性,而Builder则有可能需要多种条件都符合的时候才能生成新的对象,有一定的延时性,按通俗的话说,Abstract Factory是原材料齐全的加工厂,有需求马上就能生产;而Builder则是等待其它部件或原材料都到位的时候才能生产出新的产品。