1.5.1 模式意圖:
當面臨一個復雜對象的創(chuàng)建時锭弊,通常由各個子對象按照一定的順序組合而成玄组;隨著需求的不斷變化凫乖,復雜對象對應的各個子對象也隨之變化,但組合順序相對穩(wěn)定吟宦。我們需要將一個復雜的構(gòu)建與其表示相分離篮洁,使得同樣的構(gòu)建過程或順序可以創(chuàng)建不同的復雜對象。使用建造者模式即可達到這樣的目的殃姓。
1.5.2 模式概念:
將一個復雜的構(gòu)建與其表示相分離袁波,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。使用多個簡單的對象一步一步構(gòu)建成一個復雜的對象蜗侈。這種類型的設計模式屬于創(chuàng)建型模式篷牌,它提供了一種創(chuàng)建對象的最佳方式。
1.5.3 模式元素:
- 抽象建造者(AbstractBuilder)
- 具體建造者(HouseBuilder)
- 指揮者(Director)
- 產(chǎn)品角色(House踏幻、Cement枷颊、Brick等)
1.5.4 代碼示例:
寫一個建造房子的例子:首先你要準備水泥,鋼筋叫倍,磚塊偷卧,然后蓋一層、二層吆倦、三層直到最高層听诸,通電,通水等等多道“工序”才能完成成品蚕泽。其中每一道工序都是對產(chǎn)品的全新創(chuàng)建晌梨、但是我們只關(guān)心最后的終極產(chǎn)品---【房子】。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Custom.Log;
# region BaseClass
/// <summary>
/// 水泥
/// </summary>
public class Cement { }
/// <summary>
/// 磚塊
/// </summary>
public class Brick { }
/// <summary>
/// 鋼筋
/// </summary>
public class Rebar { }
/// <summary>
/// 樓層
/// </summary>
public class Floor { }
/// <summary>
/// 水
/// </summary>
public class Water { }
/// <summary>
/// 電
/// </summary>
public class Electricity { }
/// <summary>
/// 房屋
/// </summary>
public class House { }
#endregion
public abstract class AbstractBuilder
{
public abstract void Build_Cement();
public abstract void Build_Brick();
public abstract void Build_Rebar();
public abstract void Build_Floor();
public abstract void Build_Water();
public abstract void Build_Electricity();
public abstract House Build_House();
}
public class HouseBuilder : AbstractBuilder
{
public override void Build_Brick()
{
this.Log("建造磚塊");
}
public override void Build_Cement()
{
this.Log("建造水泥");
}
public override void Build_Electricity()
{
this.Log("建造電力");
}
public override void Build_Floor()
{
this.Log("建造樓層");
}
public override void Build_Rebar()
{
this.Log("建造鋼筋");
}
public override void Builde_Water()
{
this.Log("建造水");
}
public override House Build_House()
{
this.Log("房屋建造完成");
return new House();
}
}
public class Director
{
private AbstractBuilder abstractBuilder = null;
public Director(AbstractBuilder tempAbstractBuilder)
{
abstractBuilder = tempAbstractBuilder;
}
public House GetResult()
{
abstractBuilder.Build_Brick();//建造磚塊
abstractBuilder.Build_Cement();//建造水泥
abstractBuilder.Build_Rebar();//建造鋼筋
abstractBuilder.Build_Floor();//建造樓層
abstractBuilder.Build_Electricity();//電力完成
abstractBuilder.Build_Water();//水源完成
House temp = abstractBuilder.Builde_House();//成品房屋完成
this.Log($"完全品{temp}完成");
return temp;
}
}
調(diào)用
public class BuilderComponent : MonoBehaviour
{
void Start()
{
AbstractBuilder abstractBuilder = new HouseBuilder();
Director director = new Director(abstractBuilder);
House house = director.GetResult();
}
}
打印信息
1.5.5 寫法對比:
略
1.5.6 模式分析:
下面筆者和大家具體分析一下建造者模式须妻,其實這個和抽象工廠模式特別的相似仔蝌,都是創(chuàng)建產(chǎn)品,但建造者模式只是把原有工廠的創(chuàng)建函數(shù)交給了指揮者(Director)來執(zhí)行。從寫法上講荒吏,我認為【AbstractFactoryPlus】比【Builder】更貼切敛惊,就是讓多行的創(chuàng)建代碼演變成現(xiàn)在的
Director director = new Director(abstractBuilder);
與House house = director.GetResult();
,從結(jié)構(gòu)上看是把原本的創(chuàng)建過程再次的封裝和轉(zhuǎn)移绰更,如果想修改創(chuàng)建過程可以直接在Director類中修改瞧挤。最后通過Director組裝,在組裝的過程中可以不斷的向一個容器內(nèi)添加儡湾,獲取最終的產(chǎn)品特恬。
從職責劃分上看:
【抽象工廠】主要是沒有元素或者說一個元素對應一個產(chǎn)品,以這種方式產(chǎn)出多個產(chǎn)品徐钠。
【建造者模式】是多個元素建造一個產(chǎn)品癌刽。目的是關(guān)心一個復雜產(chǎn)品的構(gòu)建過程(再次封裝和轉(zhuǎn)移)。
指揮者(Director)主要是用于創(chuàng)建一些復雜的對象,這些對象內(nèi)部的構(gòu)建順序通常是穩(wěn)定的显拜,但對象內(nèi)部的構(gòu)建通常面臨著復雜的變化衡奥。不過真的需要建造順序更改時,我們也可以重新定義一個新的Director讼油,只需要把原有的Director類替換掉就可以杰赛,上層的改動也相對較小,絕對的開閉原則是不存在的矮台,相對的開閉才是我們應該掌握的。
【擴展說明】
或許有人會問根时,為什么不用接口代替對應的
AbstractBuilder
呢瘦赫?
筆者是這樣理解的,接口是一個獨立的功能蛤迎,不是一個系統(tǒng)确虱。以手機為例:它含有上網(wǎng)、聽音樂替裆、看電影校辩、儲存、拍照辆童、收發(fā)信息等功能宜咒,每一個功能都可以是一個接口。且這種接口具有通用性把鉴。
問什么說是通用性故黑?
例如上網(wǎng)功能接口電腦也可以繼承,拍照這種功能接口專業(yè)攝像機也可以繼承這就是通用性庭砍。這種微小獨立功能的劃分也符合接口隔離原則场晶。
但是抽象類呢,它更像一個特殊的縮小系統(tǒng)怠缸,就像手機是眾多電子產(chǎn)品中的一種诗轻,但手機的品牌很多,基于這種縮小系統(tǒng)基本一致性的特點揭北,不同的品牌扳炬,我們就可以根據(jù)手機抽象類實現(xiàn)不同的品牌實例。而且在抽象基類里面可以實現(xiàn)一些字段和函數(shù)罐呼,接口則不能鞠柄。
接口是能夠,抽象是含有嫉柴。
【舉例說明】
List這種就是集各種通用功能于一身的
這種文件操作的抽象類就很局限了
1.5.7 應用場景:
- 生成的對象具有復雜的內(nèi)部結(jié)構(gòu)厌杜。
- 生成的對象內(nèi)部屬性本身相互依賴。
1.5.8 小結(jié):
筆者認為,如果構(gòu)建過程相對簡單夯尽,2-5行代碼可以解決的問題用工廠模式就可以了瞧壮,如果十分復雜的創(chuàng)建就可以考慮下建造者模式。
建造者模式的好處就是使得建造代碼與表示代碼分離匙握,由于建造者隱藏了該產(chǎn)品的組裝順序和細節(jié)咆槽,所以若需要改變一個產(chǎn)品的內(nèi)部表示,只需要再定義一個具體的建造者(示例中的BuilderHouse)就可以了圈纺。