在某些應用中,我們想要在訪問某個對象之前執行一個或多個重要的操作,例如,訪問敏感
信息——在允許用戶訪問敏感信息之前,我們希望確保用戶具備足夠的權限。操作系統中也存在
類似的情況,用戶必須具有管理員權限才能在系統中安裝新程序。
上面提到的重要操作不一定與安全問題相關。延遲初始化
是另一個案例:我們想要把一個計算成本較高的對象的創建過程延遲到用戶首次真正使用它時
才進行。
在代理模式(Proxy Pattern)中,一個類代表另一個類的功能。這種類型的設計模式屬於結構型模式。
在代理模式中,我們創建具有現有對象的對象,以便向外界提供功能接口。
# coding: utf-8 class SensitiveInfo: def __init__(self): self.users = ['nick', 'tom', 'ben', 'mike'] def read(self): print('There are {} users: {}'.format(len(self.users), ' '.join(self.users))) def add(self, user): self.users.append(user) print('Added user {}'.format(user)) class Info: '''SensitiveInfo的保護代理''' def __init__(self): self.protected = SensitiveInfo() self.secret = '0xdeadbeef' def read(self): self.protected.read() def add(self, user): sec = input('what is the secret? ') self.protected.add(user) if sec == self.secret else print("That's wrong!") def main(): info = Info() while True: print('1. read list |==| 2. add user |==| 3. quit') key = input('choose option: ') if key == '1': info.read() elif key == '2': name = input('choose username: ') info.add(name) elif key == '3': exit() else: print('unknown option: {}'.format(key)) if __name__ == '__main__': main()
代理模式是非常重要常見的一種模式,通過組合一個現有類來改變一些方法。如下,可以通過其他方式定位元素,還能改變元素的輸入 點擊行為,難點的怎么點擊元素都在現有類的方法中實現了,寫代理類的方法很簡單。
#encoding=utf-8 import time from selenium import webdriver from selenium.webdriver.remote.webelement import WebElement class Browser(object): def __init__(self,class_): if class_ == webdriver.Chrome: self.driver = webdriver.Chrome() def find_element_through_id(self,id): self.driver.find_element_by_id(id) print '通過 ' + id + ' 查找這個元素' class Element(): def __init__(self,ele): """ :type ele:WebElement """ self.ele = ele def click(self): self.ele.click() time.sleep(2) def input(self,value): self.ele.send_keys(value) print '填了一個值: ' + value time.sleep(3) browser = Browser(webdriver.Chrome) Element(browser.find_element_through_id('shurukuang_id')).input('hello world') Element(browser.find_element_through_id('button_id')).click()
以上模式,叫代理模式。
2、認真看下,就不難發現,這貨其實也可以用繼承來解決。?
總結下區別就是:
代理在A類中 self.b = B()。self.b.fun() A類的實例通過操作成員變量b來執行方法
繼承是 class A(B)。 self.fun(),A繼承B的所有方法
那為啥要代理不要繼承?我覺得在靈活性上代理要比繼承好,例如上面的selnium例子,Broser可以組合火狐 谷歌 ie多種瀏覽器,如果繼承那就要多種繼承了。組合一個什么對象是動態的,繼承一個什么類那是固定的是的。
代理模式的類比較干凈,不會一股腦復制父類的方法,在智能ide自動補全上好很多,不會一股腦補全父類中在本類中不需用的方法,通過操作成員變量來操作一些方法。
知乎的答案就是我要說的意思。
繼承和代理都是代碼復用的方式。
繼承是把要復用的代碼(即父對象)的所有屬性和行為都復用。不管用得着用不着,先一鼓腦都繼承過來。
代理是把要復用的對象作為自己的成員變量,然后在自己的方法中通過這個成員變量去調用要復用的對象的方法。這樣就獲得了要復用的對象的部分功能,而不用把要復用的對象的全部屬性和方法都復用過來。可以稱為部分繼承或者方法借用模式。相比繼承來說,更靈活。
設計模式就是一堆組合和繼承的變幻而來。
# coding=utf-8 import time from selenium.webdriver import Chrome as ChromePatcher from selenium.webdriver.remote.webelement import WebElement def by_css(browser, *args): print 'hi' ##舉個例子,代表修改原生方法 return ChromePatcher.find_element_by_css_selector(browser, *args) ChromePatcher.by_css = by_css ###賦值,如果函數名與原類同名叫替換方法,不同名叫增加方法。 browser = ChromePatcher() browser.get('https://www.baidu.com') browser.by_css('#kw').send_keys(u'美女')
