龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > asp.net编程 >

设计模式实例之创建型模式(Singleton、Abstract Factory、Builder)讲解(2)

时间:2009-12-21 11:47来源:未知 作者:admin 点击:
分享到:
抽象工厂模式( Abstract Factory ) 抽象工厂,按字面含义来理解,就是一个不存在的工厂,只是抽象出来的一个概念工厂,反应到代码中,可以理解为定义

抽象工厂模式(Abstract Factory

抽象工厂,按字面含义来理解,就是一个不存在的工厂,只是抽象出来的一个概念工厂,反应到代码中,可以理解为定义了固定操作接口的一个抽象类,这个类不完成任何事(特殊情况也可以完成某些生产操作),而是交由它的子类来进行实际的操作。

理解概念总是困难的,因此用比喻的方式总是容易让人理解,这里我举个例子来说明抽象工厂,在我们写代码的过程中,经常会牵扯到界面元素的变动,比如常见的什么Xp样式风格、Office2003风格、Vista风格等等,例子中,我以生成文本框、复选框为例,来说明抽象工厂模式。

不论什么风格,它们都是控件,因此都会有创建文本框及复选框的方法,这些方法就是工厂方法,代码如下:

    abstract class ControlFactory
    {
        
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样式的文本框创建,则重新继承一下抽象工厂类即可,代码如下:  

    class XpControlFactory : ControlFactory
    {
        
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;
        }        
    }

 

  在客户端使用的时候,通过送入不同的实现工厂,即可实现对界面的修改,例如:

        public Panel CreateInterface(ControlFactory factory)
        {
            Panel p 
= new Panel();
            p.Controls.Add(factory.CreateCheckbox());
            p.Controls.Add(factory.CreateTextbox());
            
return p;
        }

上面的代码中,要修改不同风格的控件,只需要送入不同的抽象工厂实例即可。

 

生成器(Builder

生成器,顾名思义是负责生成内容的容器。先摘录一下书上对生成器的说明:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

初看这段话,还真有些迷糊,举个例子来说明下,现实中我们进行网络编程的时候,收到的数据包是不固定的,因此,并不知道何时能收到完整的数据包,因此,我们需要有一个过程来处理这些数据信息,而处理的过程并不适宜放在接收数据的程序模块处,因此,我们需要一个专门的类来处理这些数据包,并将其生成合适的数据包供第三方模块使用。而这个处理这些数据包的类就叫做生成器,负责将数据流生成实际需要的内容。

构建器代码示例如下(代码为了简单易读,数据流用字符串代替): 

    public class BuilderTest
    {
        
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需要提供这四个部份进行加工,需要提供接收内容的操作方法,如:PutHeadPutBodyPubHandPubFoot等,当都推入的部件符合一个布娃娃的生产条件则自动生成一个布娃娃。 

如上图所示“ReceiverObject”在代码中扮演了内容提供者,BuilderTest则负责进行数据内容分析,组合成数据对象,“UserObject”则是最终使用用户。

此时再来理解一下书中说的那句定义:“将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。“复杂对象”在此例中,就是网络传送的对象“Result”,复杂对象的构建则是指BuilderTest的处理操作。如果将BuilderTest的工作放在UserObject对象中来完成,那么在需要传送新的对象的时候,必然导致UserObject对象的修改,可实际上UserObject关心的并不是传送的数据流,而是最终的传送结果(Result),因此Builder实际上要做的事,就是将数据生成为最终使用者想要的结果。

BuilderAbstract Factory的区别:

刚开始的时候,我也觉得BuilderAbstract Factory差不多,深入了解后才发觉,它们之间也是有区别的,虽然它们都是生成新对象给使用者,也可以创建复杂对象,不过Abstract Factory是立即生成新的对象,有实时性,而Builder则有可能需要多种条件都符合的时候才能生成新的对象,有一定的延时性,按通俗的话说,Abstract Factory是原材料齐全的加工厂,有需求马上就能生产;而Builder则是等待其它部件或原材料都到位的时候才能生产出新的产品。


精彩图集

赞助商链接