通俗 Python 設計模式——介面卡模式
從這篇開始,介紹書中第二種型別的設計模式——結構型模式。結構型模式主要用於處理系統中不同實體間的關係,如 話題與評論
這類場景。今天介紹其中的介面卡模式。
介面卡模式,通俗的說就是設計 介面/api,以保證程式符合 開放/封閉 原則,保持新老程式碼間的相容性。
介面卡模式在實際開發中的使用非常頻繁,通常在系統的不同層次間,以及為系統新增擴充套件功能等場景時使用。因為通常情況下,原系統的程式碼要麼無法獲取——如庫等、要麼難以冒險重構——如執行5年以上的老舊系統牽一髮而動全身。在設計中使用介面卡模式,可以保證在不修改原系統程式碼的前提下,實現新需求與原系統的對接。
Python 實現介面卡模式有多種方式,這裡使用書中提供的示例作為介紹。
假設場景:
存在一套舊系統,裡面包含 Human
和 Synthesizer
類,如下:
class Synthesizer:
def __init__(self, name):
self.name = name
def __str__(self):
return 'the {} synthesizer'.format(self.name)
def play(self):
return 'is playing an electronic song'
class Human:
def __init__(self, name):
self.name = name
def __str__(self):
return '{} the human'.format(self.name)
def speak(self):
return 'says hello'
現在新增 Computer
類如下:
class Computer:
def __init__(self, name):
self.name = name
def __str__(self):
return 'the {} computer'.format(self.name)
def execute(self):
return 'executes a program'
並且對於擴充套件系統來說,所有動作函式均使用 Obj.execute()
來執行。即對於呼叫者來說,原系統的 Synthesizer.play()
和 Human.speak()
是不存在的,必須像呼叫 Computer.execute()
一樣使用 Synthesizer.execute()
和 Human.execute()
來呼叫原系統中物件的執行函式。
這就是我們之前提到的場景,無法修改原系統函式,此時新系統就可以採用介面卡模式進行設計。
我們可以建立一個 Adapter
類專門用於統一介面,程式碼如下。
class Adapter:
def __init__(self, obj, adapted_methods):
self.obj = obj
self.__dict__.update(adapted_methods)
def __str__(self):
return str(self.obj)
簡單來說,這裡是使用了 Python 的一個特殊語法糖 class.__dict__
屬性,即類的內部字典。這個特殊的屬性是一個字典,存放了這個類所包含的所以屬性,包括方法。所以這裡將傳入的類進行處理,將需要被介面卡處理的方法新增到內部字典中,生成一個屬於這個新介面卡物件的方法。
接下來,只需要在呼叫時,對原有系統的類進行封裝,即可實現統一使用 execute()
方法執行動作了。程式碼如下.
def main():
objects = [Computer('Asus')]
synth = Synthesizer('moog')
objects.append(Adapter(synth, dict(execute=synth.play)))
human = Human('Bob')
objects.append(Adapter(human, dict(execute=human.speak)))
for i in objects:
print('{} {}'.format(str(i), i.execute()))
簡單解釋一下,就是在例項化物件後,使用 Adapter
再將物件包裹一次,最終的呼叫其實都是呼叫了 Adapter
類的物件。這裡我們修改一下 main()
函式,在迴圈體新增一條列印物件型別的語句:
def new_main():
objects = [Computer('Asus')]
synth = Synthesizer('moog')
objects.append(Adapter(synth, dict(execute=synth.play)))
human = Human('Bob')
objects.append(Adapter(human, dict(execute=human.speak)))
for i in objects:
print('{} {}'.format(str(i), i.execute()))
print('type is {}'.format(type(i)))
執行結果如下:
the Asus computer executes a program
type is <class '__main__.Computer'>
the moog synthesizer is playing an electronic song
type is <class '__main__.Adapter'>
Bob the human says hello
type is <class '__main__.Adapter'>
可以看到,擴充套件系統實現的 Computer
類的物件因為不需要使用介面卡處理,所以被識別為 Computer
類,但是經過 Adapter
處理後的 synth
和 human
物件,已經不能被識別為 Synthesizer
和 Human
類,而是被識別為 Adapter
類了。如此一來,就實現了統一介面的目標。
從上面的例子可以看到,介面卡模式在需要進行增量式開發的系統中是非常有用的,可以在不修改舊系統的前提下,保證程式碼的一致性。在合適的場景下有效的提高了程式碼的健壯性和相容性。
其實還有一種實現方案,在 這裡 可以看到。
相關文章
- 通俗 Python 設計模式——原型設計模式Python設計模式原型
- 通俗 Python 設計模式——代理模式Python設計模式
- 通俗 Python 設計模式——工廠模式Python設計模式
- 通俗 Python 設計模式——外觀模式Python設計模式
- 通俗 Python 設計模式——建造者模式Python設計模式
- 通俗 Python 設計模式——享元模式Python設計模式
- python 設計模式-介面卡模式Python設計模式
- Python設計模式-介面卡模式Python設計模式
- python設計模式之介面卡模式Python設計模式
- 設計模式----介面卡模式設計模式
- 設計模式-介面卡模式設計模式
- 設計模式:介面卡模式設計模式
- 【設計模式】介面卡模式設計模式
- 設計模式--介面卡模式/代理模式設計模式
- JavaScript 設計模式 —— 介面卡模式JavaScript設計模式
- java設計模式-介面卡模式Java設計模式
- 設計模式(七)介面卡模式設計模式
- 設計模式之介面卡模式設計模式
- 設計模式之【介面卡模式】設計模式
- 設計模式(五):介面卡模式設計模式
- PHP設計模式_介面卡模式PHP設計模式
- 設計模式(十四):介面卡模式設計模式
- Java設計模式之介面卡設計模式Java設計模式
- PHP 設計模式之介面卡模式PHP設計模式
- Javascript 設計模式之介面卡模式JavaScript設計模式
- 設計者模式之介面卡模式模式
- Java設計模式之介面卡模式Java設計模式
- 設計模式【6.1】-- 初探介面卡模式設計模式
- Java設計模式(6)----------介面卡模式Java設計模式
- Java 設計模式(一)《介面卡模式》Java設計模式
- PHP設計模式(2)—— 介面卡模式PHP設計模式
- 極簡設計模式-介面卡模式設計模式
- 設計模式系列之「介面卡模式」設計模式
- php模式設計之 介面卡模式PHP模式
- JS 設計模式 十(介面卡模式)JS設計模式
- Java設計模式7:介面卡模式Java設計模式
- 介面卡設計模式設計模式
- 設計模式 #4 (裝飾器模式、介面卡模式)設計模式