Python設計模式-代理模式

小屋子大俠發表於2017-06-20

Python設計模式-代理模式

基於Python3.5.2,程式碼如下

#coding:utf-8

info_struct = dict()
info_struct["addr"] = 10000
info_struct["content"] = ""

class Server:
    content = ""
    def recv(self,info):
        pass
    def send(self,info):
        pass
    def show(self):
        pass

class infoServer(Server):
    def recv(self,info):
        self.content = info
        return "recv OK:"
    def send(self,info):
        pass
    def show(self):
        print("SHOW:%s"%self.content)

class serverProxy:
    pass

class infoServerProxy(serverProxy):
    server = ""
    def __init__(self,server):
        self.server = server
    def recv(self,info):
        return self.server.recv(info)
    def show(self):
        self.server.show()

class whiteInfoServerProxy(infoServerProxy):
    white_list = []
    def recv(self,info):
        try:
            assert type(info) == dict
        except:
            return "info structure is not dict"
        addr = info.get("addr",0)
        if not addr in self.white_list:
            return "Your address is not in whiteList"
        else:
            content = info.get("content","")
            return self.server.recv(content)
    def addWhite(self,addr):
        self.white_list.append(addr)
    def rmvWhite(self,addr):
        self.white_list.remove(addr)
    def clearWhite(self):
        self.white_list = []

if __name__ == "__main__":
    info_struct = dict()
    info_struct["addr"] = 10010
    info_struct["content"] = "Hello World"
    info_server = infoServer()
    white_server_proxy = whiteInfoServerProxy(info_server)
    print(white_server_proxy.recv(info_struct))
    white_server_proxy.show()
    white_server_proxy.addWhite(10010)
    print(white_server_proxy.recv(info_struct))
    white_server_proxy.show()

代理模式分析與解讀

代理模式

為某物件提供一個代理,以控制對此物件的訪問和控制。代理模式在使用過程中,應儘量對抽象主題類進行代理,而儘量不要對加過修飾和方法的子類代理。

代理模式的適用場景

1、針對某特定物件進行功能和增強性擴充套件。如IP防火牆、遠端訪問代理等技術的應用;
2、對主題物件進行保護。如大流量代理,安全代理等;
3、減輕主題物件負載。如許可權代理等。
4、為一個物件在不同的地址空間提供區域性代表,這樣可以隱藏一個物件存在於不同地址空間的事實。
5、根據需要建立開銷很大的物件,通過它來存放例項化需要很長時間的真是物件。
6、用來控制真是物件訪問的許可權。一般用於物件應該有不同的訪問許可權的是後。
7、在呼叫真是物件時,代理處理另外一些事。

解讀

在代理模式中,需要隱藏真正提供服務的物件,通過代理物件來間接呼叫服務物件。
1.先定義好真正提供服務的物件infoServer,並提供recv(),send(),show()三個方法。
2.定義好代理類infoServerProxy,當初始化代理類的時候,將需要提供服務的infoServer物件傳入,在實現infoServerProxy的三個方法recv(),send(),show()時,分別呼叫infoServer物件對應的方法,此時就實現了由代理提供對外介面服務,真正執行由隱藏的服務物件執行。
3.在whiteInfoServerProxy類中,又對代理物件進行了recv方法的封裝,當呼叫whiteInfoServerProxy.recv()方法時,會先對是否呼叫服務物件的recv()方法進行判斷,如果在white_list中能夠找到IP則執行服務物件的recv()方法。

程式執行結果如下:

Your address is not in whiteList
SHOW:
recv OK:
SHOW:Hello World

當10010不在白名單裡面的時候,返回的是Your address is not in whiteList;當白名單中有10010時,則執行成功recv OK:

代理模式的優缺點:

優點:

1.職責清晰:非常符合單一職責原則,主題物件實現真實業務邏輯,而非本職責的事務,交由代理完成;
2.擴充套件性強:面對主題物件可能會有的改變,代理模式在不改變對外介面的情況下,可以實現最大程度的擴充套件;
3.保證主題物件的處理邏輯:代理可以通過檢查引數的方式,保證主題物件的處理邏輯輸入在理想範圍內。

缺點:

1.可能會降低整體業務的處理效率和速度。

備註:

在代理模式的通用寫法可歸結如下:
class Subject():
    def request(self):
        raise NotImplementedError

class RealSubject(Subject):
    def request(self):
        print("真實請求")

class Proxy(Subject):
    def __init__(self):
        self.__realSubject = RealSubject()
    def request(self):
        self.__realSubject.request()

if __name__ == "__main__":
    # 客戶端呼叫
    proxy = Proxy()
    proxy.request()
該實現方式,更具有通用性,更適用於用不同語言對代理模式的實現。

相關文章