设计模式--建造者模式(Builder)

最近又看了下建造者模式Builder,在网上找了很多文章,但是总感觉有一些问题。 有些示例明明很像一个工厂模式,还有些示例会导致具体建造者类无限膨胀,好像都不大适合使用这个模式。
后来又对照GOF重新看了下,同时参考了http://www.cnblogs.com/happyhippy/archive/2010/09/01/1814287.html等文章,写下自己的理解。

1、定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
在以下情况使用建造者模式
• 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
• 当构造过程必须允许被构造的对象有不同的表示时。

2、示例

本人很喜欢单机武侠RPG游戏,可惜现在作品太少,新出的也是一个比一个坑。不过现在这方面的网游还不少,就使用这个来做个简单的示例。
很多游戏都会充值买礼包,比如一个礼包有名称、银两、装备(可多个)三个属性,有几种常用的礼包,也可以让玩家自由组合。而且,游戏的土豪VIP客户购买礼包还会有额外惊喜!
首先设计一个礼包类。

namespace BuilderPattern.Example
{
    /// <summary>
    /// 礼包
    /// </summary>
    public class Gift
    {
        /// <summary>
        /// 名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 银两
        /// </summary>
        public int Money { get; set; }

        /// <summary>
        /// 装备
        /// </summary>
        public IList<string> Equipments { get; set; }

        public Gift()
        {
            Equipments = new List<string>();
        }

        public void Show()
        {
            Console.WriteLine(string.Concat("购买", Name, ":"));
            Console.WriteLine("包含纹银{0}两", Money);
            if (Equipments.Count > 0)
            {
                Console.Write("包含装备:");
                foreach (var item in Equipments)
                {
                    Console.Write(string.Concat(item, " "));
                }
            }
            Console.WriteLine();
        }
    }
}

礼包有了,怎么来创建呢?首先,普通玩家和VIP玩家购买礼包的时候,礼包会有不同的表现,VIP会有额外惊喜(金钱翻倍,把所有的武器都做成土豪金的),那么尝试在创建的时候分开,使得同样的构建过程可以创建不同的表示,普通玩家和VIP玩家拿到的东西是不一样的。
我们先创建一个抽象的建造者类GiftBuilder,然后2个类GenrealGiftBuilder和BiggerGiftBuilder实现GiftBuilder,分别用来创建普通玩家的礼包和VIP玩家的礼包。

下面是相关的代码。

    /// <summary>
    /// 礼包建造者抽象类
    /// </summary>
    public abstract class GiftBuilder
    {
        /// <summary>
        /// 设置名称
        /// </summary>
        /// <param name="name"></param>
        public abstract void SetName(string name);

        /// <summary>
        /// 设置银两
        /// </summary>
        /// <param name="number"></param>
        public abstract void AddMoney(int number);

        /// <summary>
        /// 添加装备
        /// </summary>
        /// <param name="name"></param>
        public abstract void AddEquipment(string name);

        /// <summary>
        /// 返回礼包
        /// </summary>
        /// <returns></returns>
        public abstract Gift GetGift();
    }

    /// <summary>
    /// 普通礼包建造者
    /// </summary>
    public class GenrealGiftBuilder : GiftBuilder
    {
        private readonly Gift _gift = new Gift();

        public override void SetName(string name)
        {
            _gift.Name = name;
        }

        public override void AddMoney(int number)
        {
            _gift.Money += number;
        }

        public override void AddEquipment(string name)
        {
            _gift.Equipments.Add(name);
        }

        public override Gift GetGift()
        {
            return _gift;
        }
    }

    /// <summary>
    /// 土豪客户专用礼包建造者
    /// </summary>
    public class BiggerGiftBuilder : GiftBuilder
    {
        private readonly Gift _gift = new Gift();

        public override void SetName(string name)
        {
            _gift.Name = name;
        }

        public override void AddMoney(int number)
        {
            //土豪客户,金钱翻倍
            _gift.Money += number*2;
        }

        public override void AddEquipment(string name)
        {
            //土豪的装备必须是镶钻的
            _gift.Equipments.Add(string.Concat("土豪金", name));
        }

        public override Gift GetGift()
        {
            return _gift;
        }

        /// <summary>
        /// 买礼包要show出来
        /// </summary>
        /// <param name="name"></param>
        public void Show(string name)
        {
            Console.WriteLine("VIP客户{0}买大礼包啦!礼包所有金额翻倍,所有装备是土豪金的,VIP就是这么任性!", name);
        }
    }

知道怎么创建礼包了。但是有一个问题,上面的礼包里面的内容都是一个个添加进来了,这个不可能让玩家去做吧。所以游戏公司都会预设几个常用的礼包,这时候我们需要一个类来控制礼包的生成过程。
下面的Order类就是就是这个作用。

    public class Order
    {
        /// <summary>
        /// 礼包A
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public Gift GetGiftA(GiftBuilder builder)
        {
            builder.SetName("礼包A");
            builder.AddMoney(50);
            builder.AddEquipment("白虹剑");
            builder.AddEquipment("鳄鱼甲");
            builder.AddEquipment("松风剑法");
            return builder.GetGift();
        }

        /// <summary>
        /// 超级大礼包
        /// </summary>
        /// <param name="builder"></param>
        /// <returns></returns>
        public Gift GetBiggerThenBiggerGift(GiftBuilder builder)
        {
            builder.SetName("土豪大礼包");
            builder.AddMoney(10000000);
            builder.AddEquipment("倚天剑");
            builder.AddEquipment("屠龙刀");
            builder.AddEquipment("打狗棒");
            builder.AddEquipment("软猬甲");
            builder.AddEquipment("降龙十八掌");
            builder.AddEquipment("九阳真经");
            builder.AddEquipment("易筋经");
            return builder.GetGift();
        }
    }

我这里只写了2个礼包,还可以加入更多的。当然,如果玩家想自定义礼包的每一项内容,也可以单独加入一个方法,根据传入的参数来定义礼包内容。
还有,如果Order的内容越来越多,而且很多东西也类似,可以继续使用其他的设计方法来重构。

到这里,整个系统的构建就完成了,看下客户端如何调用。

    class Program
    {
        static void Main(string[] args)
        {
            var order = new Order();
            var builder = new GenrealGiftBuilder();
            var gift = order.GetGiftA(builder);
            gift.Show();

            Console.WriteLine();

            var biggerBuilder = new BiggerGiftBuilder();
            var biggerGift = order.GetBiggerThenBiggerGift(biggerBuilder);
            biggerBuilder.Show("张三");
            biggerGift.Show();

            Console.ReadLine();
        }
    }

程序的输出如下,VIP客户的待遇就是好呀!

3、总结

看看GOF对建造者模式的定义:

• Builder 抽象建造者,示例中的GiftBuilder
为创建一个Product对象的各个部件指定抽象接口
• ConcreteBuilder 具体建造者,示例中的GenrealGiftBuilder和BiggerGiftBuilder
实现Builder的接口以构造和装配该产品的各个部件
定义并明确它所创建的表示
提供一个检索产品的接口
• Director 导演类,示例中的Order
构造一个使用Builder接口的对象
• Product 产品类,示例中的Gift
表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程
包含定义组成部件的类,包括将这些部件装配成最终产品的接口

在上面的示例中,Order类可以定义各种不同的礼包,根据是否是VIP玩家,礼包也有不同的表示。而且,同样的礼包实体,可以让玩家自己选择礼包内容,只要传递金钱、装备等参数就可以。
对照着这个示例,再回顾下Builder模式的定义及使用场景:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
在以下情况使用建造者模式
• 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
• 当构造过程必须允许被构造的对象有不同的表示时。

网上也有很多类似的示例,但是有些是这样设计的:每种礼包都设计成一个具体建造者类(同BiggerGiftBuilder),但是这样的话会造成ConcreteBuilder无限膨胀。也许礼包1--5内容都差不多,就是装备有一点差别,为这个弄太多类得不偿失,况且这些类的实现其实都是一样的。

有什么问题请大家不吝指正,谢谢!

时间: 2024-08-06 07:59:02

设计模式--建造者模式(Builder)的相关文章

设计模式—建造者模式(Builder)

title: 设计模式-建造者模式 建造者模式(Builder)是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节.建造者模式属于对象创建型模式.我们获得一个对象的时候不是直接new这个对象出来,而是对其建造者进行属性设置,然后建造者在根据设置建造出各个对象出来.建造者模式又可以称为生成器模式. 模式结构 一个标准的建造者模式包含如下角色: Builder:抽象建造者 ConcreteBuilder:具体建造者 Director

23种设计模式--建造者模式-Builder Pattern

一.建造模式的介绍       建造者模式就是将零件组装成一个整体,用官方一点的话来讲就是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示.生活中比如说组装电脑,汽车等等这些都是建造者模式的具体体现,组装电脑反应到软件上就是一个复杂的对象,然后我们使用建造者模式的时候需要抽象一个建造类,抽象一个指挥者指挥具体实现的那个类,然后就是具体实现这个对象的类,这样就避免了每新创建一个不同的复杂对象就需要重新写一下这个类,这样就只要重写建造者就可以了,我们接下来就用组装电脑这个来说明一

说说设计模式~建造者模式(Builder)

返回目录 建造者模式是我的"设计模式"里创建型模式里的最后一篇,这种模式在实现中,很多架构都用到了,如MVC,MVP,MVVM,它们都是有建造者模式的精髓的,即,创建与表现分享,我们的MVC何尝不是,我们的MVVM又何尝不是呢,我们做软件的,换肤是常有的事,其实换肤的实现不就是建造者模式最好的体现吗,呵呵. 定义 将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式. 何时能用到它? 1 当创建复杂对象的算法应该独立于该对象的组成部分以

深入浅出设计模式——建造者模式(Builder Pattern)

模式动机无论是在现实世界中还是在软件系统中,都存在一些复杂的对象,它们拥有多个组成部分,如汽车,它包括车轮.方向盘.发送机等各种部件.而对于大多数用户而言,无须知道这些部件的装配细节,也几乎不会使用单独某个部件,而是使用一辆完整的汽车,可以通过建造者模式对其进行设计与描述,建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象.用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节. 在软件开发中,也存在大量类似汽车一样的复杂对象,它们拥有一系列成员属性,这些成员

建造者模式&lt;Builder&gt;

概述 将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式 角色 建造者(Builder):为创建一个产品对象的各个部件指定抽象接口. 具体建造者(ConcreteBuilder):实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并 提供一个检索产品的接口 产品(Product):表示被构造的复杂对象.ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最

C#设计模式-建造者模式

在软件系统中,有时需要创建一个复杂对象,并且这个复杂对象由其各部分子对象通过一定的步骤组合而成. 例如一个采购系统中,如果需要采购员去采购一批电脑时,在这个实际需求中,电脑就是一个复杂的对象,它是由CPU.主板.硬盘.显卡.机箱等组装而成的,如果此时让采购员一台一台电脑去组装的话真是要累死采购员了,这里就可以采用建造者模式来解决这个问题,我们可以把电脑的各个组件的组装过程封装到一个建造者类对象里,建造者只要负责返还给客户端全部组件都建造完毕的产品对象就可以了.然而现实生活中也是如此的,如果公司要

php设计模式 — 建造者模式

需求分析: 我们接到了一个订单,是宝马公司和奔驰公司的,他们负责定义产品的零部件以及型号,我们负责生产,需求简单的描述就是这样. 我们需要为这个需求设计一个设计模式去更好的适应他们的需求. 首先我们需要一个车模型类,来定义好需要的所有零部件,这就叫做抽象类,之所以这样是因为我们还有可能接到更多公司的订单,比如劳斯莱斯,宾利. 然后由各自的车来继承这个抽象类,实现里面的方法. 接下来就需要一个建造者抽象类,来定义建造各自的车需要的方法 然后由各自车建造者来继承这个抽象类. 我们会想到一个建造模式了

建造者模式(Builder)——从组装电脑开始

建造者模式(Builder)--从组装电脑开始 建造者模式概括起来就是将不同独立的组件按照一定的条件组合起来构成一个相对业务完整的对象.调用者无需知道构造的过程. 我们从组装电脑开始 让我们从买组装电脑开始吧. 首先要买一个电脑,一般都有两个选择 -- 品牌电脑和组装电脑,一般人为了省事和放心都会选择买品牌电脑(也就是整机).在这里,为了更好的分析问题,假定我们为了性价比决定要买组装电脑.那么我们该怎么做呢. 首先我们得学习一个完整的电脑的组成部分有哪些? 经过翻查一部分资料发现,主要部件分为主

C#设计模式——建造者模式(Builder Pattern)

1.建造者模式简介 1.1>.定义 建造者模式(Builder)将复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. 1.2>.使用频率  中低 1.3>.原型模式应用 在软件系统中,有时候面临一个复杂对象的创建工作,该对象通常由各个部分子对象用一定的算法构成,或者按一定的步骤组合而成:这些算法和步骤是稳定的,而构成这个对象的子对象却经常由于需求的变化而不断变化. 生活中的例子,要组装一台电脑,它的组装过程基本是不变的,都可以由主板.CPU.内存等按照某个稳定方式组合而成.