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

來源:《設計模式 可復用面向?qū)ο筌浖幕A》 ---GoF

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

1. 適配器

  1. 起源

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

  1. 方法

有兩種實現(xiàn)方法聊训,一種是繼承,一種是組合恢氯。

對于C++這樣的強類型語言來說带斑,繼承需要使用多重繼承,因為你必需繼承原始類以及要適配的接口勋拟,而對于python這種就只需要繼承原始類即可勋磕。

一般而言,組合會比繼承更靈活敢靡,而且多重繼承也容易踩坑挂滓,所以建議用組合形式。

  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)換器一個思想啸胧。

2. 橋接

  1. 起源

如果需要設計一個功能赶站,在windows和linux平臺下都能運行,同時還需要支持擴展新平臺纺念,擴展新功能亲怠,合理的做法是:將實現(xiàn)部分和抽象部分分離,抽象部分定義各個平臺的基本操作柠辞,實現(xiàn)部分使用抽象接口實現(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

### 實現(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. 思想

這里的主要思想就是將一個功能的不同部分剝離開,能夠各自獨立的擴展。

3. 組合

  1. 起源

對于又有組件又有組件聚合成的容器的系統(tǒng)习勤,如果用戶希望容器和組件一樣對待踪栋,那么可以為他們提供一個統(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. 思想

通過統(tǒng)一接口图毕,降低系統(tǒng)中的類型數(shù)量夷都。

裝飾

  1. 起源

如果希望動態(tài)的給對象增加一些職責,裝飾會比生成子類更加靈活一點予颤。

  1. 代碼
class VisualComponent(object):

    def draw():
        pass

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

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

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

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

class BorderDecorator(Decorator):
    """裝飾類"""

    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)類似囤官,但裝飾不會該表對象的職責。
  • 裝飾可以視為僅有一個組合的組合蛤虐,但它的目的不在于對象聚合党饮。
  • 裝飾并沒有改變這個對象本身,而策略會改變對象的內(nèi)核驳庭。

外觀

  1. 起源

為了提高復用度刑顺,一般子系統(tǒng)或者組件只會提供最基礎的功能,而使用者大部分情況下不會關心這些基礎組件饲常,為了降低復雜度蹲堂,會給使用者提供一個更高層次的易用的對外接口。

享元

  1. 起源

系統(tǒng)中存在大量相同的細粒度對象贝淤,可以使用共享技術有效的降低系統(tǒng)中的對象數(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):
    """被共享的對象"""

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

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

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

  1. 注意

可以用享元模式來實現(xiàn)狀態(tài)模式和策略模式能犯。

代理

  1. 起源

控制對對象的訪問,有遠程代理犬耻,虛代理,保護代理等执泰。

  1. 代碼
class Image(object):

    def __init__(self, filename):
        pass 

    def draw(self):
        pass

class ImageProxy(object):
    """保護代理枕磁,惰性加載對象"""

    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)和適配器模式以及裝飾模式很像,但他們的目的是不一樣的术吝,適配器是為了提供不一樣的接口计济,裝飾模式是為了提供額外的功能,代理模式是為了控制對對象的訪問排苍。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沦寂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子淘衙,更是在濱河造成了極大的恐慌传藏,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異毯侦,居然都是意外死亡哭靖,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門侈离,熙熙樓的掌柜王于貴愁眉苦臉地迎上來试幽,“玉大人,你說我怎么就攤上這事卦碾∑涛耄” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵洲胖,是天一觀的道長济榨。 經(jīng)常有香客問我,道長宾濒,這世上最難降的妖魔是什么腿短? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮绘梦,結(jié)果婚禮上橘忱,老公的妹妹穿的比我還像新娘。我一直安慰自己卸奉,他們只是感情好钝诚,可當我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著榄棵,像睡著了一般凝颇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上疹鳄,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天拧略,我揣著相機與錄音,去河邊找鬼瘪弓。 笑死垫蛆,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的腺怯。 我是一名探鬼主播袱饭,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼呛占!你這毒婦竟也來了虑乖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤晾虑,失蹤者是張志新(化名)和其女友劉穎疹味,沒想到半個月后仅叫,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡佛猛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年惑芭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片继找。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡遂跟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出婴渡,到底是詐尸還是另有隱情幻锁,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布边臼,位于F島的核電站哄尔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏柠并。R本人自食惡果不足惜岭接,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望臼予。 院中可真熱鬧鸣戴,春花似錦、人聲如沸粘拾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缰雇。三九已至入偷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間械哟,已是汗流浹背疏之。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留暇咆,地道東北人锋爪。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像糯崎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子河泳,可洞房花燭夜當晚...
    茶點故事閱讀 43,514評論 2 348

推薦閱讀更多精彩內(nèi)容