设计模式的征途—6.建造者(Builder)模式

建造者模式又称为生成器模式,它是一种较为复杂、使用频率也相对较低的建立型模式。建造者模式为客户端返回的不是一个简单的产品,而是一个由多个部件组成的复杂产品。由于,没有人买车会只买一个方向盘或者轮胎,你们买的都是一辆包含轮胎、方向盘和发动机等多个部件组成的完整汽车。如何将这些部件组装成一辆完整的汽车并返回给用户,这是建造者模式须要解决的问题。设计模式

建造者模式(Builder) 学习难度:★★★★☆ 使用频率:★★☆☆☆

1、从游戏角色设计谈起

M公司游戏开发部想要开发一款名为Manulife群侠传的网络游戏,该游戏采用主流的RPG(角色扮演游戏)模式,玩家能够在游戏中扮演各类特定的角色,而各个角色又能够根据不一样的游戏情节和统计数据(如力量、魔法、技能等)具备不一样的能力,角色也会随着不断升级而拥有更增强大的能力。网络

做为RPG游戏的一个重要组成部分,须要对游戏角色进行设计,并且随着该游戏的升级将不断增长新的角色。不一样类型的游戏角色,其性别、脸型、服装、发型等外部特性都有所差别,例如“天使”拥有美丽的面容和披肩的长发,并身穿一袭白裙;而“恶魔”则极其丑陋,留着光头并穿着一件刺眼的黑衣。app

M公司决定开发一个小工具来建立游戏角色,能够建立不一样类型的角色并能够灵活地增长新角色。ide

           

  【几种不一样的角色:恶魔,天使和英雄】工具

  M公司的开发人员分析发现,游戏角色是一个复杂对象,它包含性别、脸型等多个组成部分,不一样的游戏角色其组成部分有所差别,如上图所示。不管是何种造型的游戏角色,其建立步骤都大同小异,都须要逐步建立其组成部分,再将各组成部分装配成个一个完整的游戏角色。如何一步一步地建立一个包含多个组成部分的复杂对象,建造者模式为解决此类问题而诞生。学习

2、建造者模式概述

2.1 建造者模式关键定义

建造者模式(Builder):将一个复杂对象的构建与它的表示相分离,使得一样的构建过程能够建立不一样的表示。建造者模式是一种对象建立型模式。  测试

  建造者模式是一种较为复杂的建立型模式,他将客户端与包含多个组成部分的复杂对象的建立过程分离,客户端无需知道复杂对象的内部组成与装配方式,主须要知道所需的建造者便可。其关注点在于如何一步一步地建立一个复杂对象,不一样的具体建造者定义了不一样的建立过程,且具体建造者相互独立,增长新的建造者很是方便,无需修改已有代码,系统具备较好的可扩展性。ui

  

  从上图能够看出,建造者模式包含如下三类重要角色;this

  (1)Builder(抽象建造者):为建立一个产品对象的各个部件指定抽象接口,在其接口中通常包含两类方法:一类是BuildPartX(),用于建立复杂对象的各个部件;另外一类是GetResult(),用于返回生成好的复杂对象。它就能够是抽象类,也能够是接口。spa

  (2)ConcreteBuilder(具体建造者):实现了Builder接口,即实现了各个部件的具体构造和装配方法,定义并明确其所建立的复杂对象。

  (3)Product(产品角色):被构建的复杂对象,包含多个组成部件。

  (3)Director(指挥者):负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,能够在其Construct()方法中调用建造者对象的部件构造和装配方法,完成复杂对象的建造。所以,客户端只须要和指挥者进行交互,这也确保了单一职责。

2.2 建造者模式典型实现

  (1)复杂对象:包含多个成员变量的对象,这些成员也称为部件或零件。一个典型的复杂对象类以下:

    public class Product
    {
        public string PartA { get; set; }
        public string PartB { get; set; }
        public string PartC { get; set; }
    }

  (2)抽象建造者:定义了产品的建立和返回方法。

    public abstract class Builder
    {
        // 建立产品对象
        protected Product product = new Product();

        public abstract void BuildPartA();
        public abstract void BuildPartB();
        public abstract void BuildPartC();

        // 返回产品对象
        public Product GetResult()
        {
            return product;
        }
    }

  (3)指挥者对象:控制整个产品的建立过程。

    public class Director
    {
        private Builder builder;

        public Director(Builder builder)
        {
            this.builder = builder;
        }

        public void SetBuilder(Builder builder)
        {
            this.builder = builder;
        }

        // 产品构建与组装方法
        public Product Construct()
        {
            builder.BuildPartA();
            builder.BuildPartB();
            builder.BuildPartC();

            return builder.GetResult();
        }
    }

2.3 建造者模式与抽象工厂模式的对比

  建造者模式与抽象工厂模式有点类似,可是建造者模式返回一个完整的复杂产品,而抽象工厂模式则返回一系列相关的产品。若是将抽象工厂模式当作一个汽车配件生产厂,生成不一样类型的汽车配件,那么建造者模式则是一个汽车组装厂,经过对配件进行组成返回一辆完整的汽车

3、游戏角色设计实现方案

3.1 方案结构图

  以建造者模式为基础来实现游戏角色的设计,其中ActorController充当指挥者(Director),ActorBuilder充当抽象建造者,HeroBuilder、AngelBuilder和DevilBuilder充当具体建造者,Actor充当复杂产品。

3.2 具体实现

  (1)Actor:复杂产品

    /// <summary>
    /// Actor 角色类 : 复杂产品,这里只列出部分红员变量
    /// </summary>
    public class Actor
    {
        // 角色类型
        public string Type { get; set; }
        // 性别
        public string Sex { get; set; }
        // 脸型
        public string Face { get; set; }
        // 服装
        public string Costume { get; set; }
        // 发型
        public string HairStyle { get; set; }
    }

  (2)ActorBuilder:抽象建造者

    /// <summary>
    /// 角色建造器 : 抽象建造者
    /// </summary>
    public abstract class ActorBuilder
    {
        protected Actor actor = new Actor();

        public abstract void BuildType();
        public abstract void BuildSex();
        public abstract void BuildFace();
        public abstract void BuildCostume();
        public abstract void BuildHairStyle();

        // 工厂方法 : 返回一个完整的游戏角色对象
        public Actor CreateActor()
        {
            return actor;
        }
    }

  (3)HeroBuilder、AngelBuilder和DevilBuilder:具体建造者

    /// <summary>
    /// 天使角色建造器 :具体建造者
    /// </summary>
    public class AngelBuilder : ActorBuilder
    {
        public override void BuildCostume()
        {
            actor.Costume = "白裙";
        }

        public override void BuildFace()
        {
            actor.Face = "漂亮";
        }

        public override void BuildHairStyle()
        {
            actor.HairStyle = "披肩长发";
        }

        public override void BuildSex()
        {
            actor.Sex = "";
        }

        public override void BuildType()
        {
            actor.Type = "天使";
        }
    }

    /// <summary>
    /// 恶魔角色建造器 :具体建造者
    /// </summary>
    public class DevilBuilder : ActorBuilder
    {
        public override void BuildCostume()
        {
            actor.Costume = "黑衣";
        }

        public override void BuildFace()
        {
            actor.Face = "丑陋";
        }

        public override void BuildHairStyle()
        {
            actor.HairStyle = "光头";
        }

        public override void BuildSex()
        {
            actor.Sex = "";
        }

        public override void BuildType()
        {
            actor.Type = "恶魔";
        }
    }

    /// <summary>
    /// 英雄建造器 : 具体建造者
    /// </summary>
    public class HeroBuilder : ActorBuilder
    {
        public override void BuildCostume()
        {
            actor.Costume = "盔甲";
        }

        public override void BuildFace()
        {
            actor.Face = "英俊";
        }

        public override void BuildHairStyle()
        {
            actor.HairStyle = "飘逸";
        }

        public override void BuildSex()
        {
            actor.Sex = "";
        }

        public override void BuildType()
        {
            actor.Type = "英雄";
        }
    }

  (4)ActorController:指挥者

    /// <summary>
    /// 游戏角色建立控制器:指挥者(Director)
    /// </summary>
    public class ActorController
    {
        /// <summary>
        /// 逐步构建复杂产品对象
        /// </summary>
        public Actor Construct(ActorBuilder builder)
        {
            builder.BuildType();
            builder.BuildSex();
            builder.BuildFace();
            builder.BuildCostume();
            builder.BuildHairStyle();

            return builder.CreateActor(); ;
        }
    }

  (5)客户端测试

    public class Client
    {
        public static void Main(string[] args)
        {
            ActorBuilder builder = (ActorBuilder)AppConfigHelper.GetConcreteBuilderInstance();
            ActorController director = new ActorController();
            Actor actor = director.Construct(builder);

            Console.WriteLine("角色类型:{0}", actor.Type);
            Console.WriteLine("角色性别:{0}", actor.Sex);
            Console.WriteLine("角色面容:{0}", actor.Face);
            Console.WriteLine("角色服装:{0}", actor.Costume);
            Console.WriteLine("角色发型:{0}", actor.HairStyle);

            Console.ReadKey();
        }
    }

  这里仍然采用了基于配置文件的方式:将具体的构建者配置在XML文件中,如须要更改只须要更改一下配置文件便可。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="ConcreteBuilder" value="Manulife.ChengDu.DesignPattern.Builder.HeroBuilder, Manulife.ChengDu.DesignPattern.Builder" />
  </appSettings>
</configuration>

  其中AppConfigHelper类的代码以下:

    public class AppConfigHelper
    {
        public static string GetConcreteBuilderName()
        {
            string factoryName = null;
            try
            {
                factoryName = System.Configuration.ConfigurationManager.AppSettings["ConcreteBuilder"];
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return factoryName;
        }

        public static object GetConcreteBuilderInstance()
        {
            string assemblyName = AppConfigHelper.GetConcreteBuilderName();
            Type type = Type.GetType(assemblyName);

            var instance = Activator.CreateInstance(type);
            return instance;
        }
    }
View Code

  调试运行结果以下:

  

  此时若是咱们须要构建一个恶魔角色,那么修改一下配置文件:

<add key="ConcreteBuilder" value="Manulife.ChengDu.DesignPattern.Builder.DevilBuilder, Manulife.ChengDu.DesignPattern.Builder" />

  再次运行结果以下:

  

4、建造者模式小结

4.1 主要优势

  (1)客户端不须要知道产品内部的组成细节,将产品自己与产品的建立过程解耦,使得相同的建立过程能够建立不一样的产品对象。

  (2)具体建造者相对独立,增长新的具体建造者无需修改原有类库的代码,系统扩展比较方便,符合开闭原则。

  (3)能够更加精细地控制产品的建立过程 -> 将复杂产品的建立步骤分解在不一样的方法中,使得建立过程更加清晰,也更方便使用程序来控制建立过程。

4.2 主要缺点

  (1)对于所建立的产品有必定限制:通常这些产品都具备一些较多的共同点,其组成部分类似。若是差别性很大,那么则不适合使用建造者模式。

  (2)若是产品的内部结构复杂多变,可能会须要定义不少具体构建者来实现这些变化,会致使系统变得庞大,增长系统的理解难度和运行成本。

4.3 应用场景

  (1)须要生成的产品对象由复杂的内部结构,这些产品对象一般包含多个成员变量。

  (2)须要生成的产品对象的属性相互依赖,须要指定其生成顺序。

  (3)隔离复杂对象的建立和使用,并使得相同的建立过程能够建立不一样的产品。

参考资料

      DesignPattern

  刘伟,《设计模式的艺术—软件开发人员内功修炼之道》

 

相关文章
相关标签/搜索