【程序设计】Python的访问者模式

访问者模式的定义如下:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义于作用于这些元素的新操作。

提到访问者模式,就不得不提一下双分派。分派分为静态分派动态分派

静态分派即根据请求者的名称和接收到的参数,决定多态时处理的操作。

Python原生是不支持静态分派的,因而也不直接支持更高层次的分派

访问者模式实现的分派,是一种动态双分派。但这并不妨碍Python通过访问者模式实现一种基于类的“双分派效果”。

双分派顾名思义,即最终的操作决定于两个接收者的类型

优点:
1、将不同的职责非常明确地分离开来,符合单一职责原则;
2、职责的分开也直接导致扩展非常优良,灵活性非常高,加减元素和访问者都非常容易。


应用场景:
1、要遍历不同的对象,根据对象进行不同的操作的场景;或者一个对象被多个不同对象顺次处理的情况,可以考虑使用访问者模式。除本例外,报表生成器也可以使用访问者模式实现,报表的数据源由多个不同的对象提供,每个对象都是Visitor,报表这个Element顺次Accept各访问者完善并生成对象。

缺点
1、访问者得知了元素细节,与最小隔离原则相悖;
2、元素变更依旧可能引起Visitor的修改。


流程图:



python代码实现:

"""

访问者模式

假设一个药房,有一些大夫,一个药品划价员和一个药房管理员,它们通过一个药房管理系统组织工作流程。
大夫开出药方后,药品划价员确定药品是否正常,价格是否正确;
通过后药房管理员进行开药处理。
"""

# 构造药品类和工作人员类
class Medicine:
    name=""
    price=0.0
    def __init__(self,name,price):
        self.name=name
        self.price=price
    def getName(self):
        return self.name
    def setName(self,name):
        self.name=name
    def getPrice(self):
        return self.price
    def setPrice(self,price):
        self.price=price
    def accept(self,visitor):
        pass
    
    
class Antibiotic(Medicine):
    def accept(self,visitor):
        visitor.visit(self)
        
        
class Coldrex(Medicine):
    def accept(self,visitor):
        visitor.visit(self)


# 抗生素和感冒药
class Visitor:
    name=""
    def setName(self,name):
        self.name=name
    def visit(self,medicine):
        pass
    
    
class Charger(Visitor):
    def visit(self,medicine):
        print ("收费: %s 列出了药 %s. 价格:%s " \
               % (self.name, medicine.getName (), medicine.getPrice ()))


class Pharmacy(Visitor):
    def visit(self,medicine):
        print ("医生:%s 列出了药 %s. 价格:%s" \
               % (self.name, medicine.getName (), medicine.getPrice ()))


# 药方类的构建
class ObjectStructure:
    pass
class Prescription(ObjectStructure):
    medicines=[]
    def addMedicine(self,medicine):
        self.medicines.append(medicine)
    def rmvMedicine(self,medicine):
        self.medicines.append(medicine)
    def visit(self,visitor):
        for medc in self.medicines:
            medc.accept(visitor)


if __name__=="__main__":
    yinqiao_pill=Coldrex("Yinqiao Pill",2.0)
    penicillin=Antibiotic("Penicillin",3.0)
    doctor_prsrp=Prescription()
    doctor_prsrp.addMedicine(yinqiao_pill)
    doctor_prsrp.addMedicine(penicillin)
    charger=Charger()
    charger.setName("Doctor Strange")
    pharmacy=Pharmacy()
    pharmacy.setName("Doctor Wei")
    doctor_prsrp.visit(charger)
    doctor_prsrp.visit(pharmacy)



原文:https://yq.aliyun.com/articles/71075?spm=a2c4e.11153940.blogcont280715.26.175692aawkXRdB

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值