2016-12-22 19 views
0

我使用boto3爲AWS設置了一些路由。注入符合通用接口的適配器的Pythonic方法

在AWS環境中,我們希望有一個類負責將路由撥入EC2 VPC。在非AWS環境中,它會執行其他操作。

在傳統的OOP方法我將具有限定announce_route方法,例如的接口,並且創建AWSRouting或FoobarRouting的具體實例等

僞代碼來說明這種情況下:

interface Routing 
    function announceRoute() 

class AWSRouting implements Routing 

class RouteAnnouncer 
    function constructor(Routing routing) 

根據某些環境變量或配置選項,我會將適當的路由實例注入播音員。

用依賴注入實現這種適配器模式的pythonic方式是什麼?到目前爲止,我還沒有看到任何爲構造函數或設置器定義依賴類型的方法。


這是我到目前爲止有:

class RouteAnnouncer: 
    def __init__(self, adapter): 
     self.adapter = adapter 

    def announce_route(self, ip_addr): 
     self.adapter.announce_route(ip_addr) 


class AnnounceRouteContract: 
    def announce_route(self, ip_addr): 
     raise NotImplementedError 


class AWSRouting(AnnounceRouteContract): 
    def announce_route(self, ip_addr): 
     pass 


class StandardRouting(AnnounceRouteContract): 
    def announce_route(self, ip_addr): 
     pass 

所以我覺得我真正缺少的還有就是如何告訴代碼,在RouteAnnouncer適配器是用戶AnnounceRouteContract的實例。

+0

你有沒有看過[依賴注入 - python的方式](https://code.activestate.com/recipes/413268/)? –

+0

幾乎每次你認爲你需要提供你錯的類的類型。擁抱鴨子打字。 –

回答

1

您不需要做任何事情,就像創建一堆「接口」一樣近乎愚蠢。在Python中,你的界面取決於你的行爲方式。通常被稱爲「鴨子打字」,因爲如果你看起來像一隻鴨子,你像鴨子一樣走路,你像鴨子一樣嘎嘎作響,那麼你一定是一隻鴨子。

我們不在乎你是否真的一個人穿着鴨子服裝,或鴨子的紙板鏤空或機器人鴨子。這完全不相關。

它看起來像所有你真的關心你的情況是announce_route(ip_addr)是你可以調用的東西。當然,最終你希望它會設置路線,但是你知道,這就是測試的目的。

可能想要做的是有一個工廠,看起來是這樣的:

class MyRouteAnnouncer: 
    def __init__(self): 
     ... # whatever you need to do 

    def announce_route(self, ip_addr): 
     ... # do what you need to do 


def get_router(): 
    if env.is_aws(): 
     return boto3 
    elif env.is_something_else(): 
     return MyRouteAnnouncer() 
    else: 
     raise Exception('Unknown environment') 

然後不管調用get_router()功能只是得到適當的路由器和調用announce_route(ip_addr)

+0

謝謝你。這就是爲什麼我問 - 我知道我以前的思維方式可能不適用於python,所以尋找我應該採取的方法。 – bcmcfc

1

你不能強制類用戶只能通過本地python來插入特定類的實例(在python 3.6中似乎它已經實現了)。你可以只給用戶一個提示,以便IDE可以抱怨,如果沒有預期的類的實例:

class RouteAnnouncer: 
    def __init__(self, adapter): 
     """ 
     :param AnnounceRouteContract adapter: Route adapter 
     self.adapter = adapter 

也使合同摘要以及announce_route方法來強制用戶執行。你

也可以使用issubclass內置函數來檢查適配器是否是合同

1

預計在蟒蛇世界的情況下,有沒有辦法來指定參數類型。我認爲一種合適的方法是使用斷言來檢查函數內部的適配器類型。

class RouteAnnouncer: 
    def __init__(self, adapter): 
     assert isinstance(adapter, AnnounceRouteContract) 
     self.adapter = adapter