zoukankan      html  css  js  c++  java
  • 设计模式笔记(4)生成器模式(创建型)

    Gof定义

    将一个复杂对象的构建与其表示相分离,使其同样的构建过程可以创建不同的表示。

    动机

    在软件系统中,有时侯面临着一个复杂对象的创建工作,这个发展对象通常是由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂的对象的各个部分经常面临着巨大的变化,但是将他们组合起来的算法相对稳定。

    还是拿游戏中的房屋作为例子来讲,房屋由门、窗户、墙、地板、天花板组成。这些组成部分可能是经常要发生变化的。如果按常规设计,这些组成部分中的任何一个发生变化时都将使房屋重建,生成器模式的作用就是要使这些组件的变化不影响到房屋。首先构建一个House类

    public abstract class House
    {
        //该类中可能包含复杂的创建逻辑
    }

    下面的是一个抽象的构建类,用类构建房屋的组件

    public abstract class Builder
    {
        public abstract void BuildDoor();
        public abstract void BuildWall();
        public abstract void BuildWindow();
        public abstract void BuildFloor();
        public abstract void BuildHouseCeiling();
    
        public abstract House GetHouse();
    }

    假设在一个游戏管理类(GameManager)中来完成对房屋的构建

    public class GameManager
    {
        public static House CreateHouse(Builder builder)
        {
            builder.BuildDoor();
    
            builder.BuildWindow();
            builder.BuildWindow();
    
            builder.BuildWall();
            builder.BuildWall();
            builder.BuildWall();
            builder.BuildWall();
    
            builder.BuildFloor();
            builder.BuildHouseCeiling();
    
            return builder.GetHouse();
            
        }
    }

    在GameManager类中都是使用的抽象类来完成房屋的构建,所以GameManager类基本上是稳定的,可能出现变化的是创建门或是窗户的个数,当然这个我们可以在数据库中记录。稳定的部分已经创建,现在就来创建经常会变动的部分,假设现在需要构建一个罗马风格的房屋,可以写一个RomanHouse和一个RomanHouseBuilder类来继承House类和Builder类。

    public class RomanHouse:House {}
    
    public class RomanHouseBuilder : Builder
    {
        public override void BuildDoor() { }
        public override void BuildFloor() {}
        public override void BuildHouseCeiling(){ }
        public override void BuildWall(){}
        public override void BuildWindow(){}
        public override House GetHouse()
        {
            return new RomanHouse();
        }
    }

    如果需要其他风格的访问,同可以创建相应的类继承House和HouseBuilder就可以。

    客户端调用的代码如下

    public class App
    {
        public static void Main()
        {
            House house = GameManager.CreateHouse(new RomanHouseBuilder());
        }
    }

    如果需要另外的一个风格的House,只需修改GameManager.CreateHouse方法的参数为另一种风格的Builder即可,虽然这个改动很简单,但毕竟还是改变了,可以同过反射的方式来时客户程序不做任何的修改,如下:

    public class App
    {
        public static void Main()
        {
            string assemblyName = 
                ConfigurationManager.AppSettings["AssemblyName"].Trim();
            string className    = 
                ConfigurationManager.AppSettings["ClassName"].Trim();
            Assembly assembly   = Assembly.Load(assemblyName);
            Type type           = assembly.GetType(className);
            Builder builder     = Activator.CreateInstance(type) as Builder;
            House house         = GameManager.CreateHouse(builder);
        }
    }

    像上面这样改动之后,如果有新的风格的房屋需求,需要添加一套新的风格的房屋的类和Builder,然后修改下就可以了,客户程序不用做任何修改,很好的满足的OCP。

    Builder模式的几个要点

    Builder模式主要用户“分步骤构建一个复杂的对象”。在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分经常变化。变化点在哪里,封装哪里---Builder模式主要在于应对“复杂对象各个部分”的频繁需求变动。其缺点在于难以应对“分步骤构建算法”的需求变动。Abstract Factory模式解决“系列对象”的需求变化,Builder模式解决“对象部分”的需求变化。Builder模式通常和Composite模式组合使用。

    返回开篇(索引)

  • 相关阅读:
    leetcode 268. Missing Number
    DBSCAN
    python二维数组初始化
    leetcode 661. Image Smoother
    leetcode 599. Minimum Index Sum of Two Lists
    Python中的sort() key含义
    leetcode 447. Number of Boomerangs
    leetcode 697. Degree of an Array
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(1月3日)
    北京Uber优步司机奖励政策(1月2日)
  • 原文地址:https://www.cnblogs.com/oec2003/p/1607772.html
Copyright © 2011-2022 走看看