• 生成器


    生成器 Builder

    生成器是一种对象创建型模式,旨在将一个复杂对象的构建和它的表示分离。
    个人感觉的话,相比于抽象工厂,生成器就像是流水线。

    适用情况

    当创建对象的算法复杂,应该独立于对象的组成部分以及它的装配方式时。
    当构造对象的过程需要构建不同表示的对象时。

    有时候,一个对象的建造会比较复杂,特别是当它有很多个部件,每个部件又有不同的替换品(有不同的种类),各个部件的装配又要遵循某种算法。若是这个“装配算法”比较固定的话,那么使用生成器来生成对象那是再好不过了。
    (组合Composite 就是这样的一类对象,因此它通常是使用生成器来生成的)

    适用举例

    你要买一量车,除了要选型号以外,还要决定玻璃用普通玻璃还是防弹玻璃,沙发用普通沙发还是真皮沙发,加不加装其他配件等,但“组装汽车”本质上还是一样的流程。
    你要买肯打鸡套餐,套餐是饮品+汉堡+小吃,加钱还能得一个雪糕。但是饮品汉堡小吃都有不同的种类,他们最后加起来的价格也有一套算法。但是最后做出来的东西是个“套餐”是不变的。

    一款游戏,他的剑支持自定义配置,剑柄和剑身要用户进行选择。当然,在程序内部,那些商店贩卖的剑也能使用该系统。(怎么又是剑)
    (玩过猛汉王的话,就类似于贴皮武器幻化那种感觉)

    例示代码

    代码主要展示结构设计,并不一定合乎使用情理,也不一定最优。
    在这里展示的构造可能比较简单,显得生成器不是那么重要,但是在实际使用中还可能涉及到武器数值,模型拼合等比较麻烦的东西。

    基类

    就不多说了
    建造器里面封装了“为剑添加每一个部件”以及“获得造好的剑”的方法。
    相当于一个个没有组合好的车间,每个步骤封装好,但具体怎么样做还不知道。
    创造者掌管生成的算法,相当于把建造器中的车间组合成一条流水线。

    //剑
    public class Sword{/*一些代码*/}
    
    //建造器
    public class SwordBuilder
    {
        
        //一些造剑部件的方法
        public virtual void Init();//初始化一下,准备造剑
        public virtual void BuildSwordHandle(){}
        public virtual void BuildSwordBody(){}
        //返回剑的方法
        public virtual Sword GetSword(){return null};
        //这个类相当于于一个接口,不能单独实例化
        //但为了让用户只重定义他们需要的部分,需要给一些缺省值
        protected SwordBulider(){};
    }
    
    //代表剑生成算法的一个东西
    //将算法独立出来,使用算法时就不用考虑部件是具体怎么样生产的了
    public class SwordCreater
    {
        public static Sword CreateSword(SwordBuilder builder)
        {
            builder.Init();
            builder.BuildSwordHandle();
            builder.BuildSwordBody();
            return builder.GetSword();
        }
        //这里的造剑,就限定了他就那么个过程
        //如果是造车子,他就有更多的配件可以选了
    }
    

    衍生类

    上面也提到,普通的建造器是不能单独实例化的,
    因此可以写一个建造普通剑的类

    //造普通剑的建造器
    public class SampleSwordBuilder : SwordBuilder
    {
        public SampleSwordBuilder(){/*初始化代码*/}
        public override void Init(){/*一些代码*/}
        public override void BuildSwordHandle(){/*一些装剑柄的代码*/}
        public override void BuildSwordBody(){/*一些装剑身的代码*/}
        public override void GetSword(){/*将造好的剑返回出去*/}
        //一些关于造剑的代码
    }
    

    还有心心念念的自定义剑

    //自定剑建造器
    public class CustomSwordBuilder : SwordBuilder
    {
        //这一部分方法都和普通剑建造器一样,但是写起来确实是不同的
        public CustomSwordBuilder()
        {
        	m_currentHandle = "Default";
            m_currentBody = "Default";
        	//初始化代码
        }
        public override void Init(){/*一些代码*/}
        public override void BuildSwordHandle(){/*一些装剑柄的代码*/}
        public override void BuildSwordBody(){/*一些装剑身的代码*/}
        public override void GetSword(){/*将造好的剑返回出去*/}
        //一些方便用户使用的方法
        public CustomSwordBuilder(string handleType, string bodyType)
        {
            m_currentHandle = handleType;
            m_currentBody = bodyType;
            //一些代码
        }
        public void SetHandleType(string handleType)
        {
        	m_currentHandle = handleType;
        	//一些代码
        }
        public void SetBodyType(string bodyType)
        {
            m_currentBody = bodyType;
            //一些代码
        }
        //记录当前是生成什么剑
        private string m_currentHandle;
        private string m_currentBody;
        
        //一些代码
    }
    

    使用

    用户的使用就非常方便了

    //造一把普通剑
    SampleSwordBuilder ssb = new SampleSwordBuilder();
    Sword sampleSword = SwordCreater.CreateSword(ssb);
    
    //造一把自定义剑
    CustomSwordBuilder csb = new CustomSwordBuilder("Devil", "Angel");
    Sword customSword = SwordCreater.CreateSword(csb);
    

    总结

    生成器的主要思想在于将组合对象的组件生成与对象生成算法分离,从而产生更加自由地生成对象的效果。
    可能觉得与抽象工厂有些相像,因为都是用于生产复杂对象的设计模式。它与抽象工厂的主要区别是:
    抽象工厂着重于相关联的系列对象,最后得到的不止是一个对象,而且生成的对象都是立刻返回的。
    生成器着重于一步步构造一个复杂对象,最后得到得到的一般只有一个对象,生成的对象是最后一步才返回的。

    当然,可以试试用生成器调用抽象工厂的方法来生成部件,再在最后组合。就可以满足“所有部件都是同一个系列”。(那我为什么不在自定义那里用同一个引索来创建呢?个人觉得设计模式这种东西还是比较灵活的,在没遇到实际的问题之前,谁都不知道这种模式有什么用。只要在遇到问题的时候能想到还有这样的一种解决方法,就很好了)

  • 相关阅读:
    ASP'禁止网页缓存,验证码生成,删除文件 iFileName 文件名 iPath 文件路径
    ASP.NET中如何防范SQL注入式攻击
    ThickBox 2.0
    ASP.NET用户控件也可以在Web.Config中进行引用
    SQL Server数据类型介绍
    CSS和JS标签style属性对照表
    Server.UrlEncode、HttpUtility.UrlDecode的区别[两篇文章]
    使用table数据类型变量获得临时表
    关闭页面JS兼容火狐_谷歌_IE6、7、8
    SQL语句实现两个数据库表直接操作
  • 原文地址:https://www.cnblogs.com/yasoudream/p/12686435.html
Copyright © 2020-2023  润新知