参考网站: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应用案例
```csharp
public 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等)。现在你知道这两者的本质区别了嘛。