舉例講解Python設(shè)計(jì)模式編程中的訪問(wèn)者與觀察者模式
訪問(wèn)者模式
我覺(jué)得Visitor模式是在補(bǔ)修改已有程序結(jié)構(gòu)前提下,通過(guò)添加額外的訪問(wèn)者完成對(duì)代碼功能的拓展 為什么這樣用?當(dāng)你的類層次較多,在某層結(jié)構(gòu)中增加新的方法,要是在基類上面添加或者變更,可能破壞原來(lái)的設(shè)計(jì), 有兼容問(wèn)題,所以只在需要的類上面動(dòng)態(tài)添加。
python的例子
這里是個(gè)構(gòu)建車的例子,每個(gè)部件都有一個(gè)accept的方法接受我上面說(shuō)的所謂'訪問(wèn)者',而這個(gè)訪問(wèn)者 以參數(shù)的方式傳進(jìn)來(lái),但是其實(shí)他是一個(gè)含有一些功能的類的實(shí)例,它擁有很多個(gè)visit開(kāi)頭的方法對(duì)應(yīng)不同的部件。 這樣就不需要修改這些部件,而只是修改我們的訪問(wèn)者類的相關(guān)部分。
# 輪子,引擎, 車身這些定義好了都不需要變動(dòng) class Wheel: def __init__(self, name): self.name = name def accept(self, visitor): # 每個(gè)visitor是同樣的,但是其中的方法是不一樣的,比如這里是visitWheel, # 然后傳入了self,想想?他其實(shí)想做什么就能做什么 visitor.visitWheel(self) class Engine: def accept(self, visitor): visitor.visitEngine(self) class Body: def accept(self, visitor): visitor.visitBody(self) # 我們要組合成車 class Car: def __init__(self): self.engine = Engine() self.body = Body() self.wheels = [ Wheel("front left"), Wheel("front right"), Wheel("back left") , Wheel("back right") ] # 這個(gè)也不需要在動(dòng),他只是上面部件的組合,只是做了屬性的委托 def accept(self,visitor): visitor.visitCar(self) self.engine.accept(visitor) self.body.accept(visitor) for wheel in self.wheels: wheel.accept(visitor) # 這個(gè)才是我們的訪問(wèn)者,每次的修改都在這里面 class PrintVisitor: def visitWheel(self, wheel): print "Visiting "+wheel.name+" wheel" def visitEngine(self, engine): print "Visiting engine" def visitBody(self, body): print "Visiting body" def visitCar(self, car): print "Visiting car" if __name__ == '__main__': car = Car() visitor = PrintVisitor() car.accept(visitor)
觀察者模式
當(dāng)我們希望一個(gè)對(duì)象的狀態(tài)發(fā)生變化,那么依賴與它的所有對(duì)象都能相應(yīng)變化(獲得通知),那么就可以用到Observer模式, 其中的這些依賴對(duì)象就是觀察者的對(duì)象,那個(gè)要發(fā)生變化的對(duì)象就是所謂'觀察者'
python的例子
# 這個(gè)是觀察者基類 class Subject(object): def __init__(self): self._observers = [] # 添加依賴的對(duì)象 def attach(self, observer): if not observer in self._observers: self._observers.append(observer) # 取消添加 def detach(self, observer): try: self._observers.remove(observer) except ValueError: pass # 這里只是通知上面注冊(cè)的依賴對(duì)象新的變化 def notify(self, modifier=None): for observer in self._observers: # 可以設(shè)置過(guò)濾條件,對(duì)不符合過(guò)濾條件的更新 if modifier != observer: observer.update(self) # 觀察者類 class Data(Subject): def __init__(self, name=''): super(Data, self).__init__() self.name = name self._data = 0 # python2.6新增的寫法,獲取屬性為property,設(shè)置屬性為(假設(shè)屬性名字為x)@x.setter,刪除為@x.deleter @property def data(self): return self._data @data.setter def data(self, value): self._data = value self.notify() # 這里有2個(gè)被觀察者,也就是依賴的對(duì)象,每次Data有改變,這2個(gè)view都會(huì)變動(dòng) class HexViewer(object): def update(self, subject): print 'HexViewer: Subject %s has data 0x%x' % (subject.name, subject.data) class DecimalViewer(object): def update(self, subject): print 'DecimalViewer: Subject %s has data %d' % (subject.name, subject.data) if __name__ == '__main__': data1 = Data('Data 1') data2 = Data('Data 2') view1 = DecimalViewer() view2 = HexViewer() data1.attach(view1) data1.attach(view2) data2.attach(view2) data2.attach(view1) print "Setting Data 1 = 10" data1.data = 10 print "Setting Data 2 = 15" data2.data = 15 print "Setting Data 1 = 3" data1.data = 3 print "Setting Data 2 = 5" data2.data = 5 print "Update data1's view2 Because view1 is be filtered" data1.notify(modifier=view1) print "Detach HexViewer from data1 and data2." data1.detach(view2) data2.detach(view2) print "Setting Data 1 = 10" data1.data = 10 print "Setting Data 2 = 15" data2.data = 15
相關(guān)文章

使用Python Fast API發(fā)布API服務(wù)的過(guò)程詳解

Python2 Selenium元素定位的實(shí)現(xiàn)(8種)

python讀取中文路徑時(shí)出錯(cuò)(2種解決方案)

Python實(shí)現(xiàn)針對(duì)json中某個(gè)關(guān)鍵字段進(jìn)行排序操作示例

Python利用全連接神經(jīng)網(wǎng)絡(luò)求解MNIST問(wèn)題詳解

python安裝cxOracle避坑總結(jié)不要直接pip install

Django使用Celery異步任務(wù)隊(duì)列的使用