0
点赞
收藏
分享

微信扫一扫

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


示例代码

 

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

 

 

# 电表class ElecMeter:    # 抄表    def read(self):        returnrandom.randint(100, 300)    # 检查    def check(self):        returnrandom.randint(0, 1)    # 更换    def replace(self):        print('ElecMeter replaced.')    # 接受访问者    def accept(self, visitor):        visitor.visit_e_meter(self)
# 水表class WaterMeter: # 抄表 def read(self): returnrandom.randint(10, 50) # 检查 def check(self): returnrandom.randint(0, 1) # 更换 def replace(self): print('WaterMeter replaced.') # 接受访问者 def accept(self, visitor): visitor.visit_w_meter(self)
# 煤气表class GassMeter: # 抄表 def read(self): returnrandom.randint(5, 10) # 检查 def check(self): returnrandom.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:395w_value:52g_value:6ElecMeter replaced.WaterMeter replaced.GassMeter replaced.ElecMeter replaced.repair counter:4

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

 

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

阅读更多更新文章,请扫描下面二维码,关注微信公众号【面向对象思考】

举报

相关推荐

0 条评论