65.9K
CodeProject 正在变化。 阅读更多。
Home

构建器设计模式

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (20投票s)

2009年9月17日

CPOL

4分钟阅读

viewsIcon

88355

downloadIcon

656

本文展示了一个案例研究,说明我们如何在 Elizabeth 的趣味活动中使用建造者模式。

背景

在 Elizabeth 的日托中心,老师帮助孩子们搭建各种玩具,以发展他们的创造力。Elizabeth 最喜欢的活动之一是用橡皮泥制作动物。

一套模具是 Elizabeth 制作她最喜欢的酷动物时一直使用的工具。

一套模具工具包含五个部分,包括头部、身体、手臂、腿和尾巴。每当 Elizabeth 想要搭建一个动物时,她都会使用一套相同的工具来制作该动物的头部、身体、腿、手臂和尾巴,然后用胶水将它们组装起来,搭建成一个动物。孩子们可以选择许多不同类型的动物模具工具集。

例如:如果 Elizabeth 想制作一只猴子,她会选择猴子模具集开始。

  • 步骤 1. 制作猴子头部。
  • 步骤 2. 制作猴子身体。
  • 步骤 3. 制作猴子腿。
  • 步骤 4. 制作猴子手臂。
  • 步骤 5. 制作猴子尾巴。

一旦所有五个部分都完成,Elizabeth 就会将它们全部粘合在一起并进行装饰,最终制作出一只猴子。很可能,当我们去接她时,她会把它送给我们或她妈妈作为礼物(如果猴子没有装饰,她不会给我们,因为它看起来一点也不好)。当她想制作一只小猫时,她会用小猫模具集遵循相同的步骤。

在上述场景中,Elizabeth 在日常趣味活动中完美地运用了建造者设计模式。

引言

建造者设计模式帮助我们分解构建对象的各个操作。它还强制执行一个流程来创建作为成品的对象。这意味着一个对象必须经过一些指示性的步骤进行“**塑造**”后才能准备好并供他人使用。“**塑造**”过程可以应用于任何限制或业务规则,以完成构建过程(或我们用于制作被认为是可立即使用对象的对象的流程)。例如,要撰写电子邮件,在发送之前您不能将“收件人”和“主题”字段留空。换句话说,如果这两个字段未填,电子邮件对象将被视为未完成的电子邮件对象(电子邮件的常见业务规则)。它必须先被构建(填写)才能发送。本文介绍了一种实现方式,说明我们如何为 Elizabeth 的趣味活动使用建造者设计模式。

建造者设计模式结构

Builder.JPG

类图

实现代码

建造者对象

AnimalBuilder

AnimalBuilder 类是一个抽象基类。它包含构建通用产品 (Animal) 的所有构建方法。此处还声明了一个公共 Animal 对象来实现返回可立即使用对象的概念 (GetResult)。当然,它也可以是私有产品对象,在这种情况下,必须引入一个 GetResult 方法来返回一个可立即使用的产品。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace BuilderDesignPattern
    {
        public abstract class AnimalBuilder
        {
            public Animal aAnimal;

            public abstract void BuildAnimalHeader();
            public abstract void BuildAnimalBody();
            public abstract void BuildAnimalLeg();
            public abstract void BuildAnimalArm();
            public abstract void BuildAnimalTail();
        }
    }
}

MonkeyBuilder

MonkeyBuilder 类是 AnimalBuilder 的子类。它提供了 Monkey 的每个构建方法的详细信息。在此类中,我们应用所有规则来使我们的产品 (Monkey) 成为一个可立即使用的对象(装饰过的猴子)。在构造函数中,我们还将 Animal 对象 (aAnimal) 初始化为 Monkey 对象。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace BuilderDesignPattern
    {
        public class MonkeyBuilder : AnimalBuilder
        {

            public MonkeyBuilder()
            {
                aAnimal = new Monkey();
            }

            public override void BuildAnimalHeader()
            {
                aAnimal.Head = "Moneky's Head has been built";
            }

            public override void BuildAnimalBody()
            {
                aAnimal.Body = "Moneky's Body has been built";
            }

            public override void BuildAnimalLeg()
            {
                aAnimal.Leg = "Moneky's Leg has been built";
            }

            public override void BuildAnimalArm()
            {
                aAnimal.Arm = "Moneky's Arm has been built";
            }

            public override void BuildAnimalTail()
            {
                aAnimal.Tail = "Moneky's Tail has been built";
            }
        }
    }
}

KittenBuilder

MonkeyBuilder 相同,KittenBuilder 类将实现构建 Kitten 对象的详细信息。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace BuilderDesignPattern
    {
        public class KittenBuilder : AnimalBuilder
        {
            public KittenBuilder()
            {
                aAnimal = new Kitten();
            }

            public override void BuildAnimalHeader()
            {
                aAnimal.Head = "Kitten's Head has been built";
            }

            public override void BuildAnimalBody()
            {
                aAnimal.Body = "Kitten's Body has been built";
            }

            public override void BuildAnimalLeg()
            {
                aAnimal.Leg = "Kitten's Leg has been built";
            }

            public override void BuildAnimalArm()
            {
                aAnimal.Arm = "Kitten's Arm has been built";
            }

            public override void BuildAnimalTail()
            {
                aAnimal.Tail = "Kitten's Tail has been built";
            }
        }
    }
}

产品对象

动物

Animal 类是一个抽象基类,它包含产品的基本信息。它帮助我们构建多个产品。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace BuilderDesignPattern
    {
        public abstract class Animal
        {
            public string Head { get; set; }
            public string Body { get; set; }
            public string Leg { get; set; }
            public string Arm { get; set; }
            public string Tail { get; set; }

         
            //helper method for demo the Polymorphism, so we can 
            //easily tell what type object it is from client.
            public abstract void Eat();
            
            //helper method for demo the result from client
            public void ShowMe()
            {
                Console.WriteLine(Head);
                Console.WriteLine(Body);
                Console.WriteLine(Leg);
                Console.WriteLine(Arm);
                Console.WriteLine(Tail);
                Eat();

            }
        }
    }
}

Monkey 类

Monkey 类是一个由 MonkeyBuilder 构建的具体产品类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace BuilderDesignPattern
    {
        public class Monkey : Animal
        {
            //helper method to show monkey's property for demo purpose
            public override void Eat()
            {
                Console.WriteLine("Since I am Monkey, I like to eat banana");
            }
        }
    }
}

Kitten 类

Monkey 类相同,是一个由 Kittenbuilder 构建的具体产品类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace BuilderDesignPattern
    {
        public class Kitten : Animal
        {
            public override void Eat()
            {
                Console.WriteLine("Since I am Kitten, I like to eat kitten food");
            }
        }
    }
}

构造器对象

Kid 类

Kid 类是我们的构造器。它实际上驱动着具有必需的构建部件和构建动物的顺序的过程。将传入 AnimalBuilder 的具体实例,以要求不同类型的建造者,从而接收不同类型的可立即使用的对象。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace www.askbargains.com
{
    namespace BuilderDesignPattern
    {
        public class Kid
        {
            public string Name { get; set; }

            //construct process to build an animal object, 
            //after this process completed, a object 
            //will be consider as a ready to use object.
            public void MakeAnimal(AnimalBuilder aAnimalBuilder)
            {
                aAnimalBuilder.BuildAnimalHeader();
                aAnimalBuilder.BuildAnimalBody();
                aAnimalBuilder.BuildAnimalLeg();
                aAnimalBuilder.BuildAnimalArm();
                aAnimalBuilder.BuildAnimalTail();
            }


        }
    }
}

客户端应用程序

从客户端的角度来看,我创建了一个名为 Elizabeth 的 Kid(构造器对象)。Elizabeth 将使用猴子模具工具集制作一只猴子,她还将使用小猫模具工具集制作一只小猫。从客户端来看,在对象被构建后(因为它在基类 AnimalBuilder 中具有公共属性),您可以直接使用 builderA.aAnimal 作为可立即使用的对象。它也可以是一个私有字段,并通过公共方法进行访问。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using www.askbargains.com.BuilderDesignPattern;

namespace www.askbargains.com
{
    namespace Client
    {
        class Program
        {
            static void Main(string[] args)
            {
                //create a constructor object to start building
                Kid aKid = new Kid();
                aKid.Name = "Elizabeth";

                //Elizabeth use Monkey mold to make a monkey
                Console.WriteLine("{0} start making a monkey",aKid.Name);
                AnimalBuilder builderA = new MonkeyBuilder();
                aKid.MakeAnimal(builderA);
                builderA.aAnimal.ShowMe();

                //Elizabeth use Kitten mold to make a kitten
                 Console.WriteLine("{0} start making a kitten",aKid.Name);
                 AnimalBuilder builderB = new KittenBuilder();
                 aKid.MakeAnimal(builderB);
                 builderB.aAnimal.ShowMe();

                Console.Read();
            }
        }
    }
}

一旦我们启动客户端应用程序,您将看到 MonkeyKitten 都已被创建。所有相应的字段都已完成,以获得可立即使用的对象。太棒了!

BuilderOutput.JPG

结论

在本文中,我演示了如何使用建造者模式来实现一个目标,即根据某些要求将对象构建为可立即使用的状态。我还为 Elizabeth 的日托中心撰写了另一篇关于访问者设计模式的文章:Visitor_Design_Pattern.aspx

© . All rights reserved.