专业的编程技术博客社区

网站首页 > 博客文章 正文

Aha!设计模式(107)-访问者模式(3)

baijin 2024-10-01 07:32:28 博客文章 7 ℃ 0 评论

示例代码

我们使用一个接近生活的例子来说明访问者模式。假设有一个小区,居民家里一般都会安装电表、水表,部分家里会安装煤气表。

# 电表

class ElecMeter:

# 抄表

def read(self):

return random.randint(100, 300)

# 检查

def check(self):

return random.randint(0, 1)

# 更换

def replace(self):

print('ElecMeter replaced.')

# 接受访问者

def accept(self, visitor):

visitor.visit_e_meter(self)

# 水表

class WaterMeter:

# 抄表

def read(self):

return random.randint(10, 50)

# 检查

def check(self):

return random.randint(0, 1)

# 更换

def replace(self):

print('WaterMeter replaced.')

# 接受访问者

def accept(self, visitor):

visitor.visit_w_meter(self)

# 煤气表

class GassMeter:

# 抄表

def read(self):

return random.randint(5, 10)

# 检查

def check(self):

return random.randint(0, 1)

# 修理

def repair(self):

print('GassMeter repaired.')

# 接受访问者

def accept(self, visitor):

visitor.visit_g_meter(self)

上述各类分别是电表类ElemMeter,水表类WaterMeter和煤气表类GassMeter。因为是示例代码,它们的构造大部分相同,都支持抄表,检查和接受访问者功能;不同的是水表和电表支持更换,而煤气表只支持修理。由于是示例代码,所有计量表的返回值都由随机数产生。

class Home:

def __init__(self,e_meter, w_meter, g_meter):

self.e_meter= e_meter

self.w_meter= w_meter

self.g_meter= g_meter

def accept(self, visitor):

if self.e_meter:

self.e_meter.accept(visitor)

if self.w_meter:

self.w_meter.accept(visitor)

if self.g_meter:

self.g_meter.accept(visitor)

房屋类Home作为载体,管理电表,水表和煤气表的信息。当访问者入户访问时,负责将调用各计量表的accept接口以接纳访问者visitor。每个类中实际调用的函数由中各类的accept方法决定。

class MeterReader:

def __init__(self):

self.e_value= 0

self.w_value= 0

self.g_value= 0

# 抄电表

def visit_e_meter(self, e_meter):

self.e_value= self.e_value + e_meter.read()

# 抄水表

def visit_w_meter(self, w_meter):

self.w_value= self.w_value + w_meter.read()

# 抄煤气表

def visit_g_meter(self, g_meter):

self.g_value= self.g_value + g_meter.read()

# 输出结果

def __str__(self):

ret = 'e_value:'+ str(self.e_value)+ '\n'

ret = ret + 'w_value:' + str(self.w_value)+ '\n'

ret = ret + 'g_value:' + str(self.g_value) + '\n'

return ret

抄表员类MeterReader的职责就是读取所有计量表的读数值并汇总。

# 修理师傅

class MeterRepairMan:

def __init__(self):

self.repair_counter= 0

# 检查,更换电表

def visit_e_meter(self, e_meter):

ifnot e_meter.check():

e_meter.replace()

self.repair_counter= self.repair_counter + 1

# 检查,更换水表

def visit_w_meter(self, w_meter):

ifnot w_meter.check():

w_meter.replace()

self.repair_counter= self.repair_counter + 1

# 检查,修理煤气表

def visit_g_meter(self, g_meter):

ifnot g_meter.check():

g_meter.repair()

self.repair_counter= self.repair_counter + 1

# 输出结果

def __str__(self):

return 'repaircounter:' + str(self.repair_counter)

修理师傅会分别检查电表、水表、煤气表的状态,如果出现问题,就进行更换或修理。

if __name__ == '__main__':

# 构建住宅区

homes =[]

homes.append(Home(ElecMeter(),WaterMeter(), GassMeter()))

homes.append(Home(ElecMeter(), WaterMeter(),None))

# 抄表

mr =MeterReader()

for hin homes:

h.accept(mr)

print(mr)

# 检修

mrm =MeterRepairMan()

for hin homes:

h.accept(mrm)

print(mrm)

上述代码首先构建了一个两户居民的小区,然后分别接受了抄表员和检修师傅的访问,其执行结果如代码 4?62所示。由于代码中使用了随机数,因此每次结果都会不同。

e_value:395

w_value:52

g_value:6

ElecMeter replaced.

WaterMeter replaced.

GassMeter replaced.

ElecMeter replaced.

repair counter:4

只要决定了访问者类和要素类之间的关系,就可以根据需求增加具象访问者类的类型,对于任意数据结构进行访问。


觉得本文有帮助?请分享给更多人。

关注【面向对象思考】,轻松学习每一天!

有任何疑问,欢迎留言提问或讨论。

面向对象设计,面向对象编程,面向对象思考!

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表