1. 程式人生 > >建立類設計模式(5種)——原型模式

建立類設計模式(5種)——原型模式

建立類設計模式(5種)——原型模式

一、圖層

大家如果用過類似於Photoshop的平面設計軟體,一定都知道圖層的概念。圖層概念的提出,使得設計、圖形修改等操作更加便利。設計師既可以修改和繪製當前影象物件,又可以保留其它影象物件,邏輯清晰,且可以及時得到反饋。本節內容,將以圖層為主角,介紹原型模式。
首先,設計一個圖層物件。

 

class simpleLayer:
    background=[0,0,0,0]
    content="blank"
    def getContent(self):
        return self.content
    def getBackgroud(self):
        return self.background
    def paint(self,painting):
        self.content=painting
    def setParent(self,p):
        self.background[3]=p
    def fillBackground(self,back):
        self.background=back

 

在實際的實現中,圖層實現會很複雜,這裡僅介紹相關的設計模式,做了比較大的抽象,用background表示背景的RGBA,簡單用content表示內容,除了直接繪畫,還可以設定透明度。
新建圖層,填充藍底並畫一隻狗,可以簡單表示如下:

if  __name__=="__main__":
    dog_layer=simpleLayer()
    dog_layer.paint("Dog")
    dog_layer.fillBackground([0,0,255,0])
    print "Background:",dog_layer.getBackgroud()
    print "Painting:",dog_layer.getContent()

列印如下:
Background: [0, 0, 255, 0]
Painting: Dog


接下來,如果需要再生成一個同樣的圖層,再填充同樣的顏色,再畫一隻同樣狗,該如何做呢?還是按照新建圖層、填充背景、畫的順序麼?或許你已經發現了,這裡可以用複製的方法來實現,而複製(clone)這個動作,就是原型模式的精髓了。
按照此思路,在圖層類中新加入兩個方法:clone和deep_clone

 

from copy import copy, deepcopy
class simpleLayer:
    background=[0,0,0,0]
    content="blank"
    def getContent(self):
        return self.content
    def getBackgroud(self):
        return self.background
    def paint(self,painting):
        self.content=painting
    def setParent(self,p):
        self.background[3]=p
    def fillBackground(self,back):
        self.background=back
    def clone(self):
        return copy(self)
    def deep_clone(self):
        return deepcopy(self)
if  __name__=="__main__":
    dog_layer=simpleLayer()
    dog_layer.paint("Dog")
    dog_layer.fillBackground([0,0,255,0])
    print "Background:",dog_layer.getBackgroud()
    print "Painting:",dog_layer.getContent()
    another_dog_layer=dog_layer.clone()
    print "Background:", another_dog_layer.getBackgroud()
    print "Painting:", another_dog_layer.getContent()

 

列印結果如下:
Background: [0, 0, 255, 0]
Painting: Dog
Background: [0, 0, 255, 0]
Painting: Dog
clone和deep_clone有什麼區別呢?大多數程式語言中,都會涉及到深拷貝和淺拷貝的問題,一般來說,淺拷貝會拷貝物件內容及其內容的引用或者子物件的引用,但不會拷貝引用的內容和子物件本身;而深拷貝不僅拷貝了物件和內容的引用,也會拷貝引用的內容。所以,一般深拷貝比淺拷貝複製得更加完全,但也更佔資源(包括時間和空間資源)。舉個例子,下面的場景,可以說明深拷貝和淺拷貝的區別。

if  __name__=="__main__":
    dog_layer=simpleLayer()
    dog_layer.paint("Dog")
    dog_layer.fillBackground([0,0,255,0])
    print "Original Background:",dog_layer.getBackgroud()
    print "Original Painting:",dog_layer.getContent()
    another_dog_layer=dog_layer.clone()
    another_dog_layer.setParent(128)
    another_dog_layer.paint("Puppy")
    print "Original Background:", dog_layer.getBackgroud()
    print "Original Painting:", dog_layer.getContent()
    print "Copy Background:", another_dog_layer.getBackgroud()
    print "Copy Painting:", another_dog_layer.getContent()

複製程式碼

列印如下:
Original Background: [0, 0, 255, 0]
Original Painting: Dog
Original Background: [0, 0, 255, 128]
Original Painting: Dog
Copy Background: [0, 0, 255, 128]
Copy Painting: Puppy


淺拷貝後,直接對拷貝後引用(這裡的陣列)進行操作,原始物件中該引用的內容也會變動。如果將another_dog_layer=dog_layer.clone()換成another_dog_layer=dog_layer.deep_clone(),即把淺拷貝換成深拷貝,其如果如下:


Original Background: [0, 0, 255, 0]
Original Painting: Dog
Original Background: [0, 0, 255, 0]
Original Painting: Dog
Copy Background: [0, 0, 255, 128]
Copy Painting: Puppy


深拷貝後,其物件內的引用內容也被進行了複製。

 

二、原型模式

原型模式定義如下:用原型例項指定建立物件的種類,並且通過複製這些原型建立新的物件。
需要注意一點的是,進行clone操作後,新物件的建構函式沒有被二次執行,新物件的內容是從記憶體裡直接拷貝的。


f1.png

 

三、原型模式的優點和使用場景

優點:

1、效能極佳,直接拷貝比在記憶體裡直接新建例項節省不少的資源;
2、簡化物件建立,同時避免了建構函式的約束,不受建構函式的限制直接複製物件,是優點,也有隱患,這一點還是需要多留意一些。

使用場景:

1、物件在修改過後,需要複製多份的場景。如本例和其它一些涉及到複製、貼上的場景;
2、需要優化資源的情況。如,需要在記憶體中建立非常多的例項,可以通過原型模式來減少資源消耗。此時,原型模式與工廠模式配合起來,不管在邏輯上還是結構上,都會達到不錯的效果;
3、某些重複性的複雜工作不需要多次進行。如對於一個裝置的訪問許可權,多個物件不用各申請一遍許可權,由一個裝置申請後,通過原型模式將許可權交給可信賴的物件,既可以提升效率,又可以節約資源。