舉例講解Python設(shè)計(jì)模式編程中的訪問者與觀察者模式
訪問者模式
我覺得Visitor模式是在補(bǔ)修改已有程序結(jié)構(gòu)前提下,通過添加額外的訪問者完成對(duì)代碼功能的拓展 為什么這樣用?當(dāng)你的類層次較多,在某層結(jié)構(gòu)中增加新的方法,要是在基類上面添加或者變更,可能破壞原來(lái)的設(shè)計(jì), 有兼容問題,所以只在需要的類上面動(dòng)態(tài)添加。
python的例子
這里是個(gè)構(gòu)建車的例子,每個(gè)部件都有一個(gè)accept的方法接受我上面說的所謂'訪問者',而這個(gè)訪問者 以參數(shù)的方式傳進(jìn)來(lái),但是其實(shí)他是一個(gè)含有一些功能的類的實(shí)例,它擁有很多個(gè)visit開頭的方法對(duì)應(yīng)不同的部件。 這樣就不需要修改這些部件,而只是修改我們的訪問者類的相關(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è)才是我們的訪問者,每次的修改都在這里面
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è)置過濾條件,對(duì)不符合過濾條件的更新
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ù)的過程詳解
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問題詳解
python安裝cxOracle避坑總結(jié)不要直接pip install
Django使用Celery異步任務(wù)隊(duì)列的使用

