前兩篇文章介紹了單例模式和工廠模式,這兩種設計模式實際上都屬於軟件工程中的建立型模式(Creational Pattern)。維基百科有對這類模式的定義:python
在 軟件工程中, 建立型模式 是處理 對象 "對象 (計算機科學)")建立的 設計模式 "設計模式 (計算機)"),試圖根據實際狀況使用合適的方式建立對象。基本的對象建立方式可能會致使設計上的問題,或增長設計的複雜度。建立型模式經過以某種方式控制對象的建立來解決問題。
建立型模式由兩個主導思想構成。一是將系統使用的具體類封裝起來,二是隱藏這些具體類的實例建立和結合的方式。
實際上建立型模式的最大做用就是把對象的建立過程和使用過程進行了解耦,對使用者只提供接口而隱藏了具體的實現細節,讓軟件結構更清晰,更符合單一職責的原則。接下來本文將繼續介紹建立型模式中的另兩種模式——建造者模式和原型模式,文中的代碼已託管在Github上。git
建造者模式(Builder Pattern)與工廠模式相似,也是把產品的實例化過程交給專門的類來實現,不一樣的是建造者模式更多的是針對現實中一些構成較複雜,有多個組成部分的對象。好比像汽車就由車身、發動機、車輪、方向盤等不少部件組成,並且整個組裝的過程可能還要安裝必定的順序進行。github
class Car(object): """產品 """ def __init__(self, name): self.name = name self.body = None self.engine = None self.tire = None def __str__(self): info = ("Name: {}".format(self.name), "Body: {}".format(self.body), "Engine: {}".format(self.engine), "Tire: {}".format(self.tire)) return '\n'.join(info)
可是在現實使用時,用戶可能並不關心汽車的這些細節和如何將這些部件組裝成汽車的,而只是想經過特定的接口和參數得到汽車這個對象。這時就須要將這個複雜的過程抽象到到一個被稱做建造者的對象裏,建造者來負責構造這些複雜的組成:設計模式
class CarBuilder(object): """建造者 """ def __init__(self): self.car = Car("Mercedes") def add_body(self, body): self.car.body = body def add_engine(self, engine): """AMG 5.5L V8 biturbo""" self.car.engine = engine def add_tire(self, tire): self.car.tire = tire def assemble_car(self): return self.car
最後建造者模式中還會引入了一個指揮者類的角色,該類的做用主要是負責精確地控制產品的整個生成過程,根據用戶的不一樣需求返回不一樣的完整產品對象。ui
class Engineer(object): """指揮者 """ def __init__(self): self.builder = None def construct_car(self, body, engine, tire): self.builder = CarBuilder() self.builder.add_body(body) self.builder.add_engine(engine) self.builder.add_tire(tire) return self.builder.assemble_car()
只要把需求告訴指揮者,用戶就能夠得到一個產品的實例,以下所示:設計
engineer = Engineer() car = engineer.construct_car( body="G63", engine="AMG 5.5L V8 biturbo", tire="Michelin 18inch") print(car) # Output >Name: Mercedes >Body: G63 >Engine: AMG 5.5L V8 biturbo >Tire: Michelin 18inch
原型模式(Prototype design pattern)的動機是爲了讓用戶能夠經過複製對象得到一個對象的副本。此模式的出現是由於在C++和Java裏須要用此模式來更方便的拷貝對象,但在Python中要實現對一個對象的拷貝有更簡單辦法,咱們就在這裏簡單的舉個例子:code
#coding=utf-8 class Foo(object): def __init__(self, x, y): self.x = x self.y = y def __str__(self): return "id: {}, x: {}, y: {}".format(id(self), self.x, self.y) if __name__ == '__main__': foo = Foo(1, 2) # 利用deepcopy得到新對象 import copy foo1 = copy.deepcopy(foo) foo1.x = 3 foo1.y = 4 print(foo, foo1) # 利用__class__方法得到新 foo2 = foo1.__class__(5, 6) print(foo, foo2) # Output >id: 4312696592, x: 1, y: 2 id: 4312696928, x: 3, y: 4 >id: 4312696592, x: 1, y: 2 id: 4312697096, x: 5, y: 6
上面咱們用兩種原型方式實現了對Foo對象的拷貝,第一種是利用Python語言內置的deepcopy,第二種則用了更優雅的__class__方法。orm
本文介紹的兩種模式在實際使用中並不常見,建造者模式應用在構造一些複雜的對象時,好比須要構建一個HTML對象,窗口對象或者遊戲中的建模等等,而原型模式則主要應用於一些須要備份狀態的對象或新建對象開銷過大的時候。對象
[1]維基百科接口