上一篇我們用 Python 簡單的幾行程式,就可以實踐工廠方法設計模式,本篇繼續討論另一個設計模式 -- 配接器(Adapter)。
配接器就像多規格轉接頭一樣,可以連接不同介面的類別或物件,使用者可以不知道每一種類別的規格,直接呼叫配接器即可,配接器會自動將要求送至合適的插座(Socket或稱Adaptee)處理,並將結果經由配接器傳回。
圖一. 各種不同規格的插座(Socket)
圖二. 可連接多種規格的配接器(轉接頭)
我們就以插頭為例,假設插座有2孔/3孔,電壓有110V/220V之分。
# 歐規插座,一律為3孔,省略 HoleNumber 方法
class European_Socket:
def voltage(self):
return 220
# 美規插座,有2孔/3孔
class USA_Socket1:
def voltage(self):
return 110
def HoleNumber(self):
return 2
class USA_Socket2:
def voltage(self):
return 110
def HoleNumber(self):
return 3
# 配接器
class Adapter(European_Socket):
__socket = None
def __init__(self, socket = None):
self.__socket = socket
def HoleNumber(self):
# 是否為歐規
if self.__socket is None or isinstance(self.__socket, European_Socket):
return 3
return self.__socket.HoleNumber()
# 測試
socket = USA_Socket1()
adapter = Adapter(socket)
print(adapter.HoleNumber())
adapter2 = Adapter()
print(adapter2.HoleNumber())
輸出結果分別為2、3。
從以上結果知道,使用者只要知道 Adapter 規格,配接器會幫我們連接至適合的插座。
以上的範例只說明配接器的概念,但沒有彰顯設計模式的威力,以下舉聊天機器人的套件 ChatterBot為例,它是一個標準的配接器,除了內建的logic adapter,也可以自製adapter。
ChatterBot 安裝:ChatterBot 並未依賴最新版的套件,安裝可能會發生問題,必須要特殊處理。
使用 pip install chatterbot 不成功的話,必須執行 pip install chatterbot --no-dependencies,然後一一安裝依賴的套件。讀者不一定要安裝ChatterBot,如果只是要了解配接器的應用,看看下列程式即可。
首先載入套件及相關 adapter。
# 載入相關套件
from chatterbot import ChatBot
from chatterbot.trainers import ListTrainer
# 載入內建的logic adapter
bot = ChatBot(
'Built-in adapters',
storage_adapter='chatterbot.storage.SQLStorageAdapter',
logic_adapters=[
'chatterbot.logic.MathematicalEvaluation',
'chatterbot.logic.TimeLogicAdapter',
'chatterbot.logic.BestMatch'
],
database_uri='sqlite:///database.sqlite3'
)
# 時間測試:呼叫 bot.get_response。
response = bot.get_response("What time is it?")
print(f'回答:{response}')
由TimeLogicAdapter處理,輸出結果:The current time is 12:10 AM。
# 7 + 7
response = bot.get_response("What is 7 plus 7?")
print(f'回答:{response}')
由MathematicalEvaluation處理,輸出結果:7 plus 7 = 14。
例如,加上 my_adapter.MyLogicAdapter 自訂配接器。
bot = ChatBot(
'custom_adapter',
storage_adapter='chatterbot.storage.SQLStorageAdapter',
logic_adapters=[
'my_adapter.MyLogicAdapter',
'chatterbot.logic.MathematicalEvaluation',
'chatterbot.logic.BestMatch',
],
database_uri='sqlite:///database.sqlite3'
)
my_adapter.MyLogicAdapter 程式碼:
from chatterbot.logic import LogicAdapter
class MyLogicAdapter(LogicAdapter):
def __init__(self, chatbot, **kwargs):
super().__init__(chatbot, **kwargs)
def can_process(self, statement):
if statement.text.find('訂位') >= 0:
return True
return False
def process(self, input_statement, additional_response_selection_parameters):
import random
from chatterbot.conversation import Statement
# Randomly select a confidence between 0 and 1
confidence = random.uniform(0, 1)
#
answers = ['訂位日期、時間及人數?', '哪一天? 幾點? 人數呢?']
selected_statement = Statement(text=random.choice(answers))
selected_statement.confidence = confidence
return selected_statement
測試:
# 測試自訂配接器
response = bot.get_response("我要訂位")
print(f'回答:{response}')
由MyLogicAdapter處理,輸出結果:訂位日期、時間及人數?
圖三. ChatterBot 的 Adapter 處理流程
相關文件可參考『官網文件』說明。