前言
前兩篇文章介紹了單例模式和工廠模式椎麦,這兩種設計模式實際上都屬于軟件工程中的創(chuàng)建型模式(Creational Pattern)。維基百科有對這類模式的定義:
在軟件工程中野哭,創(chuàng)建型模式 是處理對象創(chuàng)建的設計模式,試圖根據實際情況使用合適的方式創(chuàng)建對象脐帝∫髦龋基本的對象創(chuàng)建方式可能會導致設計上的問題包蓝,或增加設計的復雜度驶社。創(chuàng)建型模式通過以某種方式控制對象的創(chuàng)建來解決問題。
創(chuàng)建型模式由兩個主導思想構成测萎。一是將系統(tǒng)使用的具體類封裝起來亡电,二是隱藏這些具體類的實例創(chuàng)建和結合的方式。
實際上創(chuàng)建型模式的最大作用就是把對象的創(chuàng)建過程和使用過程進行了解耦硅瞧,對使用者只提供接口而隱藏了具體的實現細節(jié)份乒,讓軟件結構更清晰,更符合單一職責的原則。接下來本文將繼續(xù)介紹創(chuàng)建型模式中的另兩種模式——建造者模式和原型模式或辖,文中的代碼已托管在Github上瘾英。
建造者模式
建造者模式(Builder Pattern)與工廠模式類似,也是把產品的實例化過程交給專門的類來實現颂暇,不同的是建造者模式更多的是針對現實中一些構成較復雜缺谴,有多個組成部分的對象。比如像汽車就由車身蟀架、發(fā)動機瓣赂、車輪、方向盤等很多部件組成片拍,而且整個組裝的過程可能還要安裝一定的順序進行。
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)
但是在現實使用時妓肢,用戶可能并不關心汽車的這些細節(jié)和如何將這些部件組裝成汽車的捌省,而只是想通過特定的接口和參數獲得汽車這個對象。這時就需要將這個復雜的過程抽象到到一個被稱作建造者的對象里碉钠,建造者來負責構造這些復雜的組成:
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
最后建造者模式中還會引入了一個指揮者類的角色纲缓,該類的作用主要是負責精確地控制產品的整個生成過程,根據用戶的不同需求返回不同的完整產品對象喊废。
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中要實現對一個對象的拷貝有更簡單辦法,我們就在這里簡單的舉個例子:
#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陆蟆,第二種則用了更優(yōu)雅的class方法。
結論
本文介紹的兩種模式在實際使用中并不常見惋增,建造者模式應用在構造一些復雜的對象時叠殷,比如需要構建一個HTML對象,窗口對象或者游戲中的建模等等诈皿,而原型模式則主要應用于一些需要備份狀態(tài)的對象或新建對象開銷過大的時候林束。
參考
[1]維基百科