設(shè)計(jì)模式02--結(jié)構(gòu)型模式

來(lái)源:《設(shè)計(jì)模式 可復(fù)用面向?qū)ο筌浖幕A(chǔ)》 ---GoF

結(jié)構(gòu)型模式

1. 適配器

  1. 起源

有一個(gè)已經(jīng)存在的類(lèi),你想使用它,但是它又不符合你的接口規(guī)范,所以你需要將其轉(zhuǎn)換成你想要的接口形式。

  1. 方法

有兩種實(shí)現(xiàn)方法,一種是繼承,一種是組合。

對(duì)于C++這樣的強(qiáng)類(lèi)型語(yǔ)言來(lái)說(shuō),繼承需要使用多重繼承,因?yàn)槟惚匦枥^承原始類(lèi)以及要適配的接口,而對(duì)于python這種就只需要繼承原始類(lèi)即可。

一般而言,組合會(huì)比繼承更靈活,而且多重繼承也容易踩坑,所以建議用組合形式。

  1. 代碼
class Adaptee(object):

    def a_useful_function(self):
        pass

class InheritAdapter(Adaptee):
    """繼承形式"""

    def interface_function(self):
        self.a_useful_function()

class CombineAdapter(object):
    """組合形式"""

    def __init__(self, adaptee):
        self._adaptee = adaptee

    def interface_function(self):
        self._adaptee.a_useful_function()
  1. 思想

跟插頭轉(zhuǎn)換器一個(gè)思想。

2. 橋接

  1. 起源

如果需要設(shè)計(jì)一個(gè)功能,在windows和linux平臺(tái)下都能運(yùn)行,同時(shí)還需要支持?jǐn)U展新平臺(tái),擴(kuò)展新功能,合理的做法是:將實(shí)現(xiàn)部分和抽象部分分離,抽象部分定義各個(gè)平臺(tái)的基本操作,實(shí)現(xiàn)部分使用抽象接口實(shí)現(xiàn)不同的功能。

  1. 代碼
class Window(object):
    
    def __init__(self, imp):
        self._imp = imp

    def draw_contents(self):
        pass

### 抽象部分
class WindowImp(object):
    
    def device_text(self):
        pass

    def device_bitmap(self):
        pass

class XWindowImp(WindowImp):

    def device_text(self):
        pass

    def device_bitmap(self):
        pass

### 實(shí)現(xiàn)部分
class ApplicationWindow(Window):

    def draw_contents(self):
        self._imp.device_text()

class IconWindow(Window):

    def draw_contents(self):
        self._imp.device_bitmap()
  1. 思想

這里的主要思想就是將一個(gè)功能的不同部分剝離開(kāi),能夠各自獨(dú)立的擴(kuò)展。

3. 組合

  1. 起源

對(duì)于又有組件又有組件聚合成的容器的系統(tǒng),如果用戶(hù)希望容器和組件一樣對(duì)待,那么可以為他們提供一個(gè)統(tǒng)一的抽象接口。

  1. 代碼
class Equipment(object):

    def add(self):
        pass

    def net_price(self):
        return 0

class FloppyDisk(Equipment):
    """組件"""

    def net_price(self):
        return 1

class CompositeEquipment(Equipment):
    """容器"""

    def __init__(self):
        self._equipment = []

    def add(self, eq):
        self._equipment.append(eq)

    def net_price(self):
        total = 0
        for eq in self._equipment:
            total += eq.net_price()
        return total
  1. 思想

通過(guò)統(tǒng)一接口,降低系統(tǒng)中的類(lèi)型數(shù)量。

裝飾

  1. 起源

如果希望動(dòng)態(tài)的給對(duì)象增加一些職責(zé),裝飾會(huì)比生成子類(lèi)更加靈活一點(diǎn)。

  1. 代碼
class VisualComponent(object):

    def draw():
        pass

class TextView(VisualComponent):
    """被裝飾的類(lèi)"""
    pass

class Decorator(VisualComponent):
    """裝飾類(lèi)的基類(lèi)"""

    def __init__(self, component):
        self._component = component

    def draw(self):
        self._component.draw()

class BorderDecorator(Decorator):
    """裝飾類(lèi)"""

    def __init__(self, component):
        self._component = component

    def draw(self):
        super(BorderDecorator, self).draw()
        self.draw_border()

    def draw_border(self):
        pass
  1. 注意
  • 與適配器結(jié)構(gòu)類(lèi)似,但裝飾不會(huì)該表對(duì)象的職責(zé)。
  • 裝飾可以視為僅有一個(gè)組合的組合,但它的目的不在于對(duì)象聚合。
  • 裝飾并沒(méi)有改變這個(gè)對(duì)象本身,而策略會(huì)改變對(duì)象的內(nèi)核。

外觀

  1. 起源

為了提高復(fù)用度,一般子系統(tǒng)或者組件只會(huì)提供最基礎(chǔ)的功能,而使用者大部分情況下不會(huì)關(guān)心這些基礎(chǔ)組件,為了降低復(fù)雜度,會(huì)給使用者提供一個(gè)更高層次的易用的對(duì)外接口。

享元

  1. 起源

系統(tǒng)中存在大量相同的細(xì)粒度對(duì)象,可以使用共享技術(shù)有效的降低系統(tǒng)中的對(duì)象數(shù)量。

  1. 代碼
class GlyphFactory(object):

    def __init__(self):
        self._character = {}

    def create_character(self, char):
        c = self._character.get(char)
        if c is None:
            self._character[char] = c = Character(char)
        return c

class Character(object):
    """被共享的對(duì)象"""

    def __init__(self, char):
        self._charcode = char

    def draw(self, window, context):
        """這里傳入外部狀態(tài)"""
        pass
  1. 思想

運(yùn)用享元模式需要區(qū)分對(duì)象的內(nèi)部狀態(tài)與外部狀態(tài),外部狀態(tài)可以在運(yùn)行時(shí)作為參數(shù)傳遞。

  1. 注意

可以用享元模式來(lái)實(shí)現(xiàn)狀態(tài)模式和策略模式。

代理

  1. 起源

控制對(duì)對(duì)象的訪(fǎng)問(wèn),有遠(yuǎn)程代理,虛代理,保護(hù)代理等。

  1. 代碼
class Image(object):

    def __init__(self, filename):
        pass 

    def draw(self):
        pass

class ImageProxy(object):
    """保護(hù)代理,惰性加載對(duì)象"""

    def __init__(self, filename):
        self._filename = filename
        self._image = None

    def get_image(self):
        if not self._image:
            self._image = Image(self._filename)
        return self._image

    def draw(self):
        self.get_image().draw()
  1. 注意

代理模式的結(jié)構(gòu)和適配器模式以及裝飾模式很像,但他們的目的是不一樣的,適配器是為了提供不一樣的接口,裝飾模式是為了提供額外的功能,代理模式是為了控制對(duì)對(duì)象的訪(fǎng)問(wèn)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容