参考网站:https://blog.csdn.net/liaoshengg/article/details/82078997
参考网站:https://blog.csdn.net/lxt610/article/details/81325731
建造者注重物体创建过程的理解:http://dingxiaowei.cn/2017/05/16/
一、定义
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
理解:
以创建角色为例,角色组装可以使用工厂模式来生成角色对象,但是如果要对角色(双方士兵)作不同差异功能的时候就要再次分开写两个新的工厂类(我方士兵工厂类,敌方士兵工厂类),如果要对士兵类添加新的功能,则可以往工厂类添加方法。但是这样做会让工厂管理类越来越复杂
这时可以用到建造者模式了:将一个复杂对象的构建流程与它的对象表现分离出来,让相同的构建流程可以产生出不同的对象行为的表现。
比如说配置一辆车子时,都会按照一定的步骤来组装准备车架-> 外观烤漆 -> 将引擎放入车架 -> 装入内装椅,此时就把组装的流程定义好了,但是具体的需求完全可以由我们来设定
二、适用场景
- 需要生成的产品对象有复杂的内部结构,这些产品对象具备共性;
隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品;
三、组成部分
建造者中的角色如下:
1、Builder:给出一个抽象/接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。
2、ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。
3、Director:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。该类有一个方法,明确定义对象组装的流程,即调用Builder接口方法的顺序
4、Product:所要创建的复杂对象, 必须提供方法让Builder类可以将各部分功能设置给它四、简单案例
/// <summary>/// 产品类,由多个部件组成/// </summary>public class Product{/// <summary>/// 产品部件集合/// </summary>IList<string> parts = new List<string>();/// <summary>/// 添加产品部件/// </summary>/// <param name="part"></param>public void Add(string part){parts.Add(part);}public void Show(){Console.WriteLine("\n产品 创建 ==>>>");foreach (string part in parts){Console.WriteLine(part);}}}
/// <summary>/// 抽象建造者类/// 确定产品的两个部件PartA、PartB,/// 并声明一个得到产品建造后果的方法GetResult./// </summary>public abstract class Builder{public abstract void BuildPartA();public abstract void BuildPartB();public abstract Product GetResult();}
class ConcreteBuilder1 : Builder{private Product product = new Product();public override void BuildPartA(){product.Add("部件A");}public override void BuildPartB(){product.Add("部件B");}public override Product GetResult(){return product;}}public class ConcreteBuilder2 : Builder{private Product product = new Product();public override void BuildPartA(){product.Add("X部件");}public override void BuildPartB(){product.Add("Y部件");}public override Product GetResult(){return product;}}
class Director{/// <summary>/// 用来指挥创建过程/// </summary>/// <param name="builder"></param>public void Construct(Builder builder){builder.BuildPartA();builder.BuildPartB();}}
```csharp Director director = new Director(); Builder b1 = new ConcreteBuilder1(); Builder b2 = new ConcreteBuilder2();
director.Construct(b1); Product p1 = b1.GetResult(); p1.Show();
director.Construct(b2); Product p2 = b2.GetResult(); p2.Show(); ———————————————— 输出: 产品 创建 ==>>> 部件A 部件B 产品 创建 ==>>> X部件 Y部件
<a name="uPfZP"></a>## 五、优缺点优点:<br />1.易于解耦,将产品本身与产品创建过程进行解耦,可以使用相同的创建过程来得到不同的产品。也就说细节依赖抽象。<br />2.易于精确控制对象的创建,将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰<br />3.易于拓展,增加新的具体建造者无需修改原有类库的代码,易于拓展,符合“开闭原则“。<br />**综述:**每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。<br />缺点<br /> 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。<br /> 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。<a name="nJY5k"></a>## 六、Unity应用案例```csharppublic class UIView{protected Text mText;protected Text mBtnText;protected Image mImage;public void Init(Transform transform){mText = Instantiate(transform, "UIView/MyText").GetComponent<Text>();Button button = Instantiate(transform, "UIView/Button").GetComponent<Button>();mBtnText = transform.Find("Button(Clone)/Text").GetComponent<Text>();mImage = Instantiate(transform, "UIView/Image").GetComponent<Image>();}protected GameObject Load(string path){return Resources.Load<GameObject>(path);}protected GameObject Instantiate(Transform parent, string path){GameObject go = GameObject.Instantiate(Load(path));GameObject goNew = GameObject.Find("");go.transform.SetParent(parent, false);//go.transform.localScale = Vector3.one;//go.transform.position = go.transform.position;return go;}}
public class Product{List<UIView> parts = new List<UIView>();public void Add(UIView go){if (go is ConcreteBuilder1)parts.Add(go as ConcreteBuilder1);if (go is ConcreteBuilder2)parts.Add(go as ConcreteBuilder2);}public void Show(){foreach (UIView go in parts){if (go is ConcreteBuilder1){ConcreteBuilder1 b1 = go as ConcreteBuilder1;b1.BuilderMethodA();}if (go is ConcreteBuilder2){(go as ConcreteBuilder2).BuilderMethodA();}}}}
public abstract class Builder : UIView{public abstract void BuilderMethodA();public abstract Product GetResult();}
public class ConcreteBuilder1 : Builder{private Product product = new Product();public override void BuilderMethodA(){mText.text = "建造者A";mBtnText.text = "建造者A按钮";mImage.color = Color.red;}public override Product GetResult(){return product;}}public class ConcreteBuilder2 : Builder{private Product product = new Product();public override void BuilderMethodA(){mText.text = "建造者B";mBtnText.text = "建造者B按钮";mImage.color = Color.green;}public override Product GetResult(){return product;}}
public class Director{public void Construct(Builder builder){builder.BuilderMethodA();}}
public class Test : MonoBehaviour {void OnGUI(){if (GUI.Button(new Rect(100, 100, 120, 50), "按钮1")){Director director = new Director();Builder b1 = new ConcreteBuilder1();b1.Init(this.transform);director.Construct(b1);Product p1 = b1.GetResult();p1.Show();}if (GUI.Button(new Rect(100, 200, 120, 50), "按钮2")){Director director = new Director();Builder b2 = new ConcreteBuilder2();b2.Init(this.transform);director.Construct(b2);Product p2 = b2.GetResult();p2.Show();}}}
如果在此基础上有对于建造过程有所限制呢?例如创建了A则不能创建B,或者创建了A则必须创建B
创建过程校验的理解:http://dingxiaowei.cn/2017/05/16/
工厂模式VS建造者模式
如果刚接触建造者模式,可能会有个疑惑,同样都是创建型模式,而且都是创建对象这种创建型模式,那么它们之间的区别是什么呢?从我的理解来讲,我觉得工厂模式是注重创建不同类型的产品,从宏观上体现出差别,举个例子,还是汽车厂商通用公司,它下面有各种类型的汽车品牌工厂,雪佛兰、别克、凯迪拉克等工厂,每个工厂生产出来的产品是不一样的,而建造者模式我认为是体现了”建造”这样的流程,例如我要生产一个汽车,那么汽车厂在生产的过程是一条流水线,先生产什么,再生产什么,最后有装配车间去组装,重点是在建造的过程上。所以说差异性在以下两个方面:
- 意图不同
在工厂模式中,我们关注的是一个产品整体,无需关心产品各个部分是如何生产出来的,但建造者模式中,一个具体产品的生产是依赖各个部件的产生以及装配顺序,它关注的是由”零部件一步一步地组装产品对象”。简单来说,工厂模式是一个对象创建的组线条应用,建造者模式则是通过细线条勾勒出一个复杂对象,关注的是产品组成部分的创建过程。工厂方法模式注重产品本身,而建造者模式注重产品创建过程。 - 复杂度不同
工厂方法模式的产品一般是单一性质产品,例如各个不同品牌的汽车,他们都是汽车模样,而建造者模式创建一个复合产品,它由各个零部件组成,部件不同产品对象也当然不同。不是说工厂模式创建的对象简单,而是只他们的粒度大小不同。一般来说,工厂方法模式的对象比较粗,建造者模式的产品对象粒度比较细。
两者的区别有了,那么在具体应用中,我们该如何选择呢?使用工厂模式创建对象,还是用建造者模式来创建对象。这取决于我们在做设计的意图,是关心最终的产品的零部件生产、组装过程,还是说想得到不同的产品。就像上面举例的创建一个角色,我们需要给他创建各个零部件,然后组合成一个角色,还记得工厂模式的例子嘛,生产不同类型的武器,生产不同品牌的汽车,Unity中创建不同类型的UI(Button、Text、Toggle等)。现在你知道这两者的本质区别了嘛。
