构建器设计模式






4.78/5 (20投票s)
本文展示了一个案例研究,说明我们如何在 Elizabeth 的趣味活动中使用建造者模式。
背景
在 Elizabeth 的日托中心,老师帮助孩子们搭建各种玩具,以发展他们的创造力。Elizabeth 最喜欢的活动之一是用橡皮泥制作动物。
一套模具是 Elizabeth 制作她最喜欢的酷动物时一直使用的工具。
一套模具工具包含五个部分,包括头部、身体、手臂、腿和尾巴。每当 Elizabeth 想要搭建一个动物时,她都会使用一套相同的工具来制作该动物的头部、身体、腿、手臂和尾巴,然后用胶水将它们组装起来,搭建成一个动物。孩子们可以选择许多不同类型的动物模具工具集。
例如:如果 Elizabeth 想制作一只猴子,她会选择猴子模具集开始。
- 步骤 1. 制作猴子头部。
- 步骤 2. 制作猴子身体。
- 步骤 3. 制作猴子腿。
- 步骤 4. 制作猴子手臂。
- 步骤 5. 制作猴子尾巴。
一旦所有五个部分都完成,Elizabeth 就会将它们全部粘合在一起并进行装饰,最终制作出一只猴子。很可能,当我们去接她时,她会把它送给我们或她妈妈作为礼物(如果猴子没有装饰,她不会给我们,因为它看起来一点也不好)。当她想制作一只小猫时,她会用小猫模具集遵循相同的步骤。
在上述场景中,Elizabeth 在日常趣味活动中完美地运用了建造者设计模式。
引言
建造者设计模式帮助我们分解构建对象的各个操作。它还强制执行一个流程来创建作为成品的对象。这意味着一个对象必须经过一些指示性的步骤进行“**塑造**”后才能准备好并供他人使用。“**塑造**”过程可以应用于任何限制或业务规则,以完成构建过程(或我们用于制作被认为是可立即使用对象的对象的流程)。例如,要撰写电子邮件,在发送之前您不能将“收件人”和“主题”字段留空。换句话说,如果这两个字段未填,电子邮件对象将被视为未完成的电子邮件对象(电子邮件的常见业务规则)。它必须先被构建(填写)才能发送。本文介绍了一种实现方式,说明我们如何为 Elizabeth 的趣味活动使用建造者设计模式。
建造者设计模式结构
类图
实现代码
建造者对象
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();
}
}
}
}
一旦我们启动客户端应用程序,您将看到 Monkey
和 Kitten
都已被创建。所有相应的字段都已完成,以获得可立即使用的对象。太棒了!
结论
在本文中,我演示了如何使用建造者模式来实现一个目标,即根据某些要求将对象构建为可立即使用的状态。我还为 Elizabeth 的日托中心撰写了另一篇关于访问者设计模式的文章:Visitor_Design_Pattern.aspx。