python开发中常用的设计模式(装饰者模式)

原文取自大话设计模式,这里将其改为python代码进行实现

 需求:现有一个用户,实现其穿衣服、穿裤子、打领带的功能,并保证其扩展性。


# 菜鸟代码

class Person():
    name = ""

    def __init__(self, name):
        self.name = name

    def WearTShirts(self):
        print("大T恤")

    def WearBigTrouse(self):
        print("垮裤")

    def WearSneakers(self):
        print("破球鞋")

    def WearSuit(self):
        print("西装")

    def WearTie(self):
        print("领带")

    def WearLeatherShoes(self):
        print("皮鞋")

    def Show(self):
        print("我的装扮是:"+self.name)


if __name__ == '__main__':
    print("第一种装扮:")
    person1=Person("程序猿")
    person1.WearBigTrouse()
    person1.WearLeatherShoes()
    person1.WearSneakers()
    person1.Show()

    print("第二种装扮:")
    person2=Person("程序猿")
    person2.WearSuit()
    person2.WearTie()
    person2.WearTShirts()
    person2.Show()

# 上述代码扩展性很差,不遵守开放封闭原则

上面的代码完全没有扩展性,仿佛就是针对某个特定用户实现一样。

如若添加其它的衣服种类,或其他的用户,则上面的代码就要over了。

需求大量改变时。。。更。。。

 

对上面的代码进行改进:


import abc


class Person():
    name=""
    def __init__(self,name):
        self.name=name
    def show(self):
        print("装扮的:"+self.name)

class Finery():
    @abc.abstractmethod
    def show(self):
        pass

class Thirts(Finery):
    def show(self):
        print("大T恤")


class WearBigTrouse(Finery):
    def show(self):
        print("垮裤")

class WearSneakers(Finery):
    def show(self):
        print("破球鞋")

class WearSuit(Finery):
    def show(self):
        print("西装")

class WearTie(Finery):
    def show(self):
        print("领带")

class WearLeatherShoes(Finery):
    def show(self):
        print("皮鞋")

if __name__ == '__main__':

    print("第一种装扮:")
    person=Person("程序猿")
    dtx=Thirts()
    kk=WearBigTrouse()
    pqx=WearSneakers()
    dtx.show()
    kk.show()
    pqx.show()
    person.show()


    print("第二种装扮:")
    person=Person("程序猿")
    dtx=WearSuit()
    kk=WearLeatherShoes()
    pqx=WearTie()
    dtx.show()
    kk.show()
    pqx.show()
    person.show()

# 上面的代码将各种服装进行了扩展,但是调用起来还是方便

改进的代码虽然对衣服类进行了抽象封装,具有了扩展性,但是调用起来非常麻烦。

比如说:当上面的【程序猿】穿任意一个衣服时,都要将这个【裸体】【程序猿】进行传递,没有串起来。

即【程序猿】穿了【上衣】后、常规来讲肯定是将【穿过上衣的程序猿】传递给【下一个衣服】。

而不是将【裸体】的【程序猿】进行传递。

即没有按需进行顺序控制。

 

对上述的代码再次改版,用装饰者模式进行实现:

装饰者模式:动态的给对象添加一些额外的职责!


import abc

# 定义一个对象的接口,动态的给对象添加职责
class Component():
    @abc.abstractmethod
    def Operation(self):
        pass


# 具体的装饰对象,给具体的对象添加职责或功能
class ConcreteComPonent(Component):

    def __init__(self):
        print("我是小明,我是一个对象!!")

    def Operation(self):
        print("我要开始穿衣服了.....")


# 装饰抽象类,从外类来扩展对象的接口的方法,这个类就是用扩展对象接口的
# 这个类主要用来服务具体的装饰对象的,即保留服务对象
# 其中component指的就是服务对象-小明

class Decorator(Component):
    component=None

    def __init__(self):
        print("创建了装饰对象")

    def setComponent(self,component):
        self.component=component


    def Operation(self):
        if self.component!=None:
            self.component.Operation()


# 装饰对象A
class ConcreteDecoratorA(Decorator):

    addedState="A"
    def __init__(self):
        print("创建了装饰A对象")


    def Operation(self):
        super().Operation()
        self.addedState="修改装饰对象A的属性为:AAAAA"
        print("穿上衣")

# 装饰对象B
class ConcreteDecoratorB(Decorator):
    addedState="B"

    def __init__(self):
        print("创建了装饰B对象")

    def Operation(self):
        super().Operation()
        self.addedState="修改装饰对象B的属性为:BBBBB"
        print("穿裤子")

    # 装饰对象B独有的操作
    def AddedBehavior(self):
        print("开始吃饭")


if __name__ == '__main__':
    # 具体的装饰对象
    c=ConcreteComPonent()
    # 创建装饰对象A
    a1=ConcreteDecoratorA()
    # 创建装饰对象B
    b1=ConcreteDecoratorB()

    # 将具体对象小明传给装饰对象A,这句话执行后装饰对象A中包含了小明,即A(小明)
    a1.setComponent(c)

    # 装饰对象A 传给装饰对象B,这句话执行后,装饰对象B中包含了A,即B(A(小明))
    b1.setComponent(a1)

    # 开始执行穿衣操作
    b1.Operation()

    b1.AddedBehavior()

这个模式的精髓在于将【对象】装进A、将【A】装进【B】,最后调用【B】的独有方法(等同于一条线将所有事情串起来)

注:也可以在A中创建A独有的方法并且调用,然后再传给B

其中:

调用【B】的方法时、会获取到【A】(因为B对象的component这时候存储的时A)

注:对象【A】是通过Super()方法获取到的,没有这个方法则获取不到

获取到【A】后,调用了其Operation()方法,然后通过这个方法得到了【小明】,与上述同理,也是通过Super()方法获取到的小明,然后A再调用自己的方法!!!

运行结果如下:

调用的时候有点像递归,即一层一层网上走,走到最顶层是,开始一层一层往下执行。

稍微有点难理解,但明白了还是很有帮助的。

一定要注意Super()方法,整个代码都围绕着这个方法在转!!

一定要注意Super()方法,整个代码都围绕着这个方法在转!!

一定要注意Super()方法,整个代码都围绕着这个方法在转!!

如有错误,敬请指正!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值