[原译]理解并实现生成器模式

介绍

本文讨论生成器设计模式,讨论该模式什么情况下使用,怎么实现。并且。最后会有一个简单的生成器模式的实现。

 

背景

当我们的程序需要创建一个对象。而这个对象必须由很多不同的对象来构造的时候。为了构造最后的对象。我们不得不组合那些部分对象。最后我们会发现我们的代码被各种各样的部分对象的细节所弄的难以理解

 

为了说明上面的情况。我们做一个手机生产制造系统的例子。假定我们我们有一个已经安装在手机供应商那块的一个系统。现在供应商系那个要根据一些参数来创造一个新手机。比如触屏,操作系统,电池等。如果我们已经有了这些部分的对象,那么上述部分的任意组合将会导致客户端代码复杂难以管理。比如决定生产哪种手机的模块。

 

生成器模式目的就是解决上述问题的。GoF定义生成器模式如下:

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

 

 

这个定义意味着我们不得不设计这个系统。通过一种客户端仅仅定义参数,而生成器则接管创建复杂对象 的方式。我们看一下生成器模式的类图。

 

然后看看上图中的每一个类都表示什么

ConcreteBuilder: 创建复杂产品的具体类.将会知道他已经创建的Product(产品),也就是他已经装配了的Product, 客户端通过该类得到Product对象.

Builder: 创建Product的接口

Director: 客户端代码,定义了哪些部分应该被组合在一起来创建具体的Product

Product: 这是通过组合很多部分创建的对象

 

使用代码

我们现在跟随上述的定义,然后试着去实现一个基本的生成器模式

 

我们先在合适的地方定义Product的不同部分,我们简单的定义一些枚举类型,那么我们就可以通过组合不同的部分创建Product了。

 

// 一些helper枚举定义各种零件

public enum ScreenType

{

    ScreenType_TOUCH_CAPACITIVE,

    ScreenType_TOUCH_RESISTIVE,

    ScreenType_NON_TOUCH

};

public enum Battery

{

    MAH_1000,

    MAH_1500,

    MAH_2000

};

public enum OperatingSystem

{

    ANDROID,

    WINDOWS_MOBILE,

    WINDOWS_PHONE,

    SYMBIAN

};

public enum Stylus

{

    YES,

    NO

};

 

 

然后,我们看一下Product类,我们需要有一个可以通过装配创建的Product类,这里我们定义一个MobilePhone类,也就是概念里的Product类了。

 

// 这是 "Product" 类

class MobilePhone

{

    // 不同部分的字段

    string phoneName;      

    ScreenType phoneScreen;

    Battery phoneBattery;

    OperatingSystem phoneOS;

    Stylus phoneStylus;

    public MobilePhone(string name)

    {

        phoneName = name;

    }

    //公有属性访问这些部分

    public string PhoneName

    {

        get { return phoneName; }           

    }

    public ScreenType PhoneScreen

    {

        get { return phoneScreen; }

        set { phoneScreen = value; }

    }       

    public Battery PhoneBattery

    {

        get { return phoneBattery; }

        set { phoneBattery = value; }

    }       

    public OperatingSystem PhoneOS

    {

        get { return phoneOS; }

        set { phoneOS = value; }

    }      

    public Stylus PhoneStylus

    {

        get { return phoneStylus; }

        set { phoneStylus = value; }

    }

    // 显示手机相关信息的方法

    public override string ToString()

    {

        return string.Format("Name: {0}\nScreen: {1}\nBattery {2}\nOS: {3}\nStylus: {4}",

            PhoneName, PhoneScreen, PhoneBattery, PhoneOS, PhoneStylus);

    }

}

 

既然我们已经有了Product类,我们来创建Builder吧。Builder类应该提供一些方法可以手机的任何部分。这样我们创建IPhoneBuilder ,也就是概念里的Builder,然后看代码:

 

 

// 这是 "Builder" 类

interface IPhoneBuilder

{

    void BuildScreen();

    void BuildBattery();

    void BuildOS();

    void BuildStylus();

    MobilePhone Phone { get;}

}

 

现在我们的Builder接口也准备好了。下一步就是创建ConcreteBuilder了。我们假定供应商事项要一个android手机和一个WP手机。我们就需要两个ConcreteBuilder了。AndroidPhoneBuilder 和  WindowsPhoneBuilder. 在这两个Builder里。我们可以指定每个手机需要的零件类型
// 这是 "ConcreteBuilder" 类

class AndroidPhoneBuilder : IPhoneBuilder

{

    MobilePhone phone;

    public AndroidPhoneBuilder()

    {

        phone = new MobilePhone("Android Phone");

    }

    #region IPhoneBuilder Members

    public void BuildScreen()

    {

        phone.PhoneScreen = ScreenType.ScreenType_TOUCH_RESISTIVE;

    }

    public void BuildBattery()

    {

        phone.PhoneBattery = Battery.MAH_1500;

    }

    public void BuildOS()

    {

        phone.PhoneOS = OperatingSystem.ANDROID;

    }

    public void BuildStylus()

    {

        phone.PhoneStylus = Stylus.YES;

    }

    // 返回创建的手机对象

    public MobilePhone Phone

    {

        get { return phone; }

    }

    #endregion

}

 

//这是 "ConcreteBuilder" 类

class WindowsPhoneBuilder : IPhoneBuilder

{

    MobilePhone phone;

    public WindowsPhoneBuilder()

    {

        phone = new MobilePhone("Windows Phone");

    }

    #region IPhoneBuilder Members

    public void BuildScreen()

    {

        phone.PhoneScreen = ScreenType.ScreenType_TOUCH_CAPACITIVE;

    }

    public void BuildBattery()

    {

        phone.PhoneBattery = Battery.MAH_2000;

    }

    public void BuildOS()

    {

        phone.PhoneOS = OperatingSystem.WINDOWS_PHONE;

    }

    public void BuildStylus()

    {

        phone.PhoneStylus = Stylus.NO;

    }

    //返回创建的手机对象

    public MobilePhone Phone

    {

        get { return phone; }

    }

    #endregion

}

 

最后我们来创建Director类,我们创建的Director类将会有一个组合函数接受一个IPhoneBuilder 参数,然后调用各自ConcreteBuilder内部的对应方法

// 这是"Director" 类

class Manufacturer

{

    public void Construct(IPhoneBuilder phoneBuilder)

    {

        phoneBuilder.BuildBattery();

        phoneBuilder.BuildOS();

        phoneBuilder.BuildScreen();

        phoneBuilder.BuildStylus();

    }

}

 

现在我们已经以标准的生成器模式封装了生产复杂Products的方法。现在我们看一下客户端要创建一个Product的时候有多简单。

 

class Program

{

    static void Main(string[] args)

    {

        // 首先创建Director

        Manufacturer newManufacturer = new Manufacturer();

        // 然后创建 Builder

        IPhoneBuilder phoneBuilder = null;

        // 创建一个Android手机吧

        phoneBuilder = new AndroidPhoneBuilder();

        newManufacturer.Construct(phoneBuilder);

        Console.WriteLine("A new Phone built:\n\n{0}", phoneBuilder.Phone.ToString());

        // 再创建一个WP手机

        phoneBuilder = new WindowsPhoneBuilder();

        newManufacturer.Construct(phoneBuilder);

        Console.WriteLine("A new Phone built:\n\n{0}", phoneBuilder.Phone.ToString());

    }

}

 

现在啊,我们如果还要创建更多的对象,仅仅再需要一个ConcreteBuilder类,其他的代码一点都不会动。客户端代码也更容易来创建复杂Product了。我们看看程序输出。

 

最后看一下我们通过生成器模式写的程序的类图。

Demo下载

Builder Pattern 

 

许可

本文包括源代码和文件在CPOL下授权

原文地址:Understanding-and-Implementing-Builder-Pattern-in

 

著作权声明:本文由http://leaver.me 翻译,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!

posted @ 2012-10-08 13:18  lazycoding  阅读(1542)  评论(1编辑  收藏  举报