建造者模式的適用範圍:想要建立一個由多個部分組成的對象,並且它的構成須要一步接一步的完成。只有當各個部分都完成了,這個對象才完整。建造者模式表現爲複雜對象的建立與表現相分離,這樣,同一個過程就有不一樣的表現。django
假設咱們要建立一個HTML頁面生成器就可使用建造者模式。該模式中,有兩個參與者:建造者(builder)和指揮者(director)。建造者負責建立負責對象的各個組成部分。在HTML例子中,這些組成部分包括:頁面標題、文本標題、內容主體和頁腳。指揮者使用一個建造者實例控制建造的過程。對於HTML示例,這裏指調用建造者的函數設置頁面標題、文本標題等。使用不一樣的建造者實例讓咱們能夠建立不一樣的HTML頁面,而無需更換指揮者代碼。設計模式
1. 現實生活中的例子編輯器
快餐店使用的便是建造者設計模式。即便存在多種漢堡包(經典款、奶酪漢堡包等等)和不一樣的包裝(大、中、小盒子等),準備一個漢堡包及打包(盒子或者紙袋)的流程都是同樣的。兩種漢堡包的區別在於表現,而不在於建造的過程。指揮者是出納員,將須要準備什麼餐品的指令傳達給工做人員,即建造者。ide
2. 軟件的例子函數
本文一開始提到的HTML例子,在django-widgy中獲得了實際應用。django-widgy是一個Django的第三方樹編輯器擴展,可用做內容管理系統。它包含一個網頁構建器,用來建立具備不一樣佈局的HTML頁面。佈局
django-query-builder是另外一個基於建造者模式的Django第三方擴展庫,該擴展庫可用於動態地構建SQL查詢。使用它,咱們能夠控制一個查詢的方方面面,並能建立不一樣種類的查詢。學習
3. 應用案例ui
若是咱們知道一個對象必須通過多個步驟來建立,而且要求同一個構造過程可用於產生不一樣的表現,就可使用建造者模式。例如頁面生成器、文檔轉換器以及用戶界面等等。設計
工廠模式與建造者模式的區別在於工廠模式以單個步驟建立對象,而建造者模式以多個步驟建立對象,且幾乎始終使用一個指揮者。一些有針對性的建造者模式實現並未使用指揮者,如Java的StringBuffer。orm
另外一個區別是,在工廠模式下,會當即返回一個建立好的對象;而在建造者模式下,僅須要時客戶端代碼才顯示地請求指揮者返回最終的對象。
新電腦類比的例子可能會有助於區分建造者模式和工廠模式。假設你想買一臺新電腦,若是決定購買一臺特定的預配置的電腦型號,例如,最新的蘋果1.4GHz Mac mini,則是使用工廠模式。全部硬件的規格都已經有製造商預先肯定,製造商不用向你諮詢就知道本身該作些什麼,它們一般接收的僅僅是單條指令。代碼以下
MINI14 = '1.4GHz Mac mini'
class AppleFactory:
class MacMini14:
def __init__(self):
self.memory = 4 # 單位爲GB
self.hdd = 500 # 單位爲GB
self.gpu = 'Intel HD Graphics 5000'
def __str__(self):
info = ('Model: {}'.format(MINI14),'Memory: {}GB'.format(self.memory),'Hard Disk: {}GB'.format(self.hdd),'Graphics Card: {}'.format(self.gpu))
return '\n'.join(info)
def build_computer(self, model):
if (model == MINI14):
return self.MacMini14()
else:
print("I dont't know how to build {}".format(model))
if __name__ == '__main__':
afac = AppleFactory()
mac_mini = afac.build_computer(MINI14)
print(mac_mini)
另外一個選擇是購買一臺定製的PC。倘若這樣,使用的便是建造者模式。你是指揮者,向製造商(建造者)提供指令說明心中理想的電腦規格。
class Computer:
def __init__(self, serial_number):
self.serial = serial_number
self.memory = None # 單位爲GB
self.hdd = None # 單位爲GB
self.gpu = None
def __str__(self):
info = ('Memory: {}GB'.format(self.memory),'Hard Disk: {}GB'.format(self.hdd),'Graphics Card: {}'.format(self.gpu))
return '\n'.join(info)
class ComputerBuilder:
def __init__(self):
self.computer = Computer('AG23385193')
def configure_memory(self, amount):
self.computer.memory = amount
def configure_hdd(self, amount):
self.computer.hdd = amount
def configure_gpu(self, gpu_model):
self.computer.gpu = gpu_model
class HardwareEngineer:
def __init__(self):
self.builder = None
def construct_computer(self, memory, hdd, gpu):
self.builder = ComputerBuilder()①
[step for step in (self.builder.configure_memory(memory),self.builder.configure_hdd(hdd),self.builder.configure_gpu(gpu))]
@property
def computer(self):
return self.builder.computer
def main():
engineer = HardwareEngineer()
engineer.construct_computer(hdd=500, memory=8, gpu='GeForce GTX 650 Ti')
computer = engineer.computer
print(computer)
if __name__ == '__main__':
main()
基本的變化是引入了一個建造者ComputerBuilder、一個指揮者HardwareEngineer以及一步接一步裝配一臺電腦的過程,這樣如今就支持不一樣的配置了(注意, memory、 hdd及gpu是形參並未預先設置)。
4. 小結
本章中,咱們學習瞭如何使用建造者設計模式。能夠在工廠模式(工廠方法或抽象工廠)不適用的一些場景中使用建造者模式建立對象。在如下幾種狀況下,與工廠模式相比,建造者模式是更好的選擇。
[ ] 想要建立一個複雜對象(對象由多部分組成,且建立對象的過程結果許多步驟,也許這些步驟還須要特定的順序)。
[ ] 要求一個對象有許多不一樣的表現,並但願對象的構造與表現得耦合度低
[ ] 想要在不一樣得時間建立對象
咱們看到了快餐店如何將建造者模式用於準備食物,兩個第三方Django擴展包( django-widgy和django-query-builder)各自如何使用建造者模式來生成HTML頁面和動態的SQL查詢。咱們重點學習了建造者模式與工廠模式之間的區別,經過對預先配置(工廠)電腦與客戶定製(建造者)電腦進行訂單類比來理清這兩種設計模式。
以上就是本文的所有內容,但願對你們的學習有所幫助,也但願你們多多支持。