[Python设计模式] 第6章 衣服搭配系统——装饰模式

题目

设计一个控制台程序,可以给人搭配嘻哈风格(T恤,垮裤,运动鞋)或白领风格(西装,领带,皮鞋)的衣服并展示,类似QQ秀那样的。

基础版本

class Person():

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

    def wear_T_shirts(self):
        print("T恤")

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

    def wear_sneakers(self):
        print("运动鞋")

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

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

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

    def show(self):
        print("装扮的{}".format(self.name))

客户端代码

def main():
    hezhang = Person("张贺")
    print("第一种装扮")
    hezhang.wear_T_shirts()
    hezhang.wear_big_trouser()
    hezhang.wear_sneakers()
    hezhang.show()

    print("第二种装扮")
    hezhang.wear_suit()
    hezhang.wear_tie()
    hezhang.wear_leather_shoes()
    hezhang.show()

main()
第一种装扮
T恤
垮裤
运动鞋
装扮的张贺
第二种装扮
西装
领带
皮鞋
装扮的张贺

点评

  • 仅实现了基本功能
  • 如果添加“超人”装扮,需要如何做?需要在Person类中改代码;
  • 如果Person类除了穿衣服,还要支持吃饭,睡觉等功能,需要如何做?需要在Person类中改代码;
  • 综上,需要把“服饰”类和“人”类分离。

改进版本1.0——人衣分离

class Person():

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

    def show(self):
        print("装扮的{}".format(self.name))

from abc import ABCMeta, abstractmethod

class Finery(metaclass=ABCMeta):

    @abstractmethod
    def show(self):
        pass

class TShirts(Finery):

    def show(self):
        print("T恤")

class BigTrouser(Finery):

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

class Sneakers(Finery):

    def show(self):
        print("运动鞋")

class Suit(Finery):

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

class Tie(Finery):

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

class LeatherShoes(Finery):

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

客户端代码

def main():
    hezhang = Person("张贺")
    print("第一种装扮")
    t_shirts = TShirts()
    big_trouser = BigTrouser()
    sneakers = Sneakers()

    t_shirts.show()
    big_trouser.show()
    sneakers.show()
    hezhang.show()

    print("第二种装扮")
    suit = Suit()
    tie = Tie()
    leather_shoes = LeatherShoes()
    suit.show()
    tie.show()
    leather_shoes.show()
    hezhang.show()

main()
第一种装扮
T恤
垮裤
运动鞋
装扮的张贺
第二种装扮
西装
领带
皮鞋
装扮的张贺

点评

分析以下代码:

    hezhang = Person("张贺")
    t_shirts = TShirts()
    big_trouser = BigTrouser()
    sneakers = Sneakers()

    t_shirts.show()
    big_trouser.show()
    sneakers.show()
    hezhang.show()

用自然语言描述就是:

  • 先实例化出hezhang这个人类,准确的说,是没有穿衣服的人类;
  • 再实例化并穿上出各种衣服,T恤,垮裤,运动鞋等;
  • 再展示出来hezhang

但是服饰和人之间好像没有任何关系,那么如何用代码表示:

  • 实例化没穿衣服的人类
  • 为没穿衣服的人类穿上T恤
  • 为穿着T恤的人类穿上垮裤
  • 为穿着T恤,垮裤的人类穿上运动鞋

这需要用到装饰模式。

装饰模式

装饰模式,为了动态的给一个对象添加一些额外的职责,就增加功能而言,装饰模式比生成子类更为灵活[DP]。

装饰模式有以下几个主要组成部分:

  • 组件类Component:定义一个对象接口, 可以给这些对象动态的添加职责;
  • 具体组件类ConcretComponent:定义了一个具体对象,也可以给这个对象添加一些职责;
  • 装饰类Decorator:装饰抽象类,继承Component,从外类来扩展Component类的功能,对于Component而言,无需知道Decorator的存在;
  • 具体装饰类ConcretDecorator:具体装饰类,为Component添加职责

用代码表示:

from abc import ABCMeta, abstractmethod

class Component(metaclass=ABCMeta):
    """
    组件类Component:定义一个对象接口, 可以给这些对象动态的添加职责
    """
    @abstractmethod
    def operation(self):
        pass

class ConcreteComponent(Component):
    """
    具体组件类ConcretComponent:定义了一个具体对象,也可以给这个对象添加一些职责
    """
    def operation(self):
        print("具体组件的操作")

class Decorator(Component):
    """
    装饰类Decorator:装饰抽象类,继承Component,从外类来扩展Component类的功能,对于Component而言,无需知道Decorator的存在;
    """
    def __init__(self):
        self.component = None

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

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

class ConcreteDecratorA(Decorator):
    """
    具体装饰类ConcretDecorator:具体装饰类,为Component添加职责
    """
    def __init__(self):
        self.added_operation = "A:具体装饰类A独有操作"

    def operation(self):
        super().operation()
        print(self.added_operation)
        print("A:具体装饰对象A的操作")

class ConcreteDecratorB(Decorator):
    """
    具体装饰类ConcretDecorator:具体装饰类,为Component添加职责
    """
    def __init__(self):
        self.added_operation = "B:具体装饰类B独有操作"

    def operation(self):
        super().operation()
        print(self.added_operation)
        print("B:具体装饰对象B的操作")
def main():
    component = ConcreteComponent()
    decorator_a = ConcreteDecratorA()
    decorator_b = ConcreteDecratorB()

    decorator_a.set_component(component)
    decorator_b.set_component(decorator_a)
    decorator_b.operation()

main()
具体组件的操作
A:具体装饰类A独有操作
A:具体装饰对象A的操作
B:具体装饰类B独有操作
B:具体装饰对象B的操作

改进版本2.0——装饰模式

from abc import ABCMeta,abstractmethod

class Person():
    """
    人物类(组件类)
    """
    def __init__(self, name):
        self.name = name

    def show(self):
        print("装扮的{}".format(self.name))

class Finery(Person):
    """
    服饰类(装饰类)
    """
    def __init__(self):
        self.component = None

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

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

class TShirts(Finery):
    """
    具体装饰类
    """
    def show(self):
        print("T恤")
        super().show()

class BigTrouser(Finery):
    """
    具体装饰类
    """
    def show(self):
        print("垮裤")
        super().show()

class Sneakers(Finery):
    """
    具体装饰类
    """
    def show(self):
        print("运动鞋")
        super().show()

class Suit(Finery):
    """
    具体装饰类
    """
    def show(self):
        print("西装")
        super().show()

class Tie(Finery):
    """
    具体装饰类
    """
    def show(self):
        print("领带")
        super().show()

class LeatherShoes(Finery):
    """
    具体装饰类
    """
    def show(self):
        print("皮鞋")
        super().show()

客户端代码

def main():
    hezhang = Person("张贺")
    t_shirts = TShirts()
    big_trouser = BigTrouser()
    sneakers = Sneakers()

    t_shirts.decorate(hezhang)
    big_trouser.decorate(t_shirts)
    sneakers.decorate(big_trouser)
    sneakers.show()

main()
运动鞋
垮裤
T恤
装扮的张贺

点评

上述客户端代码可以用自然语言描述为:

  • 实例化没穿衣服的人类
  • 为没穿衣服的人类穿上T恤
  • 为穿着T恤的人类穿上垮裤
  • 为穿着T恤,垮裤的人类穿上运动鞋

所以,装饰模型是为已有功能动态的添加更多功能的一种方式,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户端代码可以在运行时根据需要有选择的,按顺序的使用装饰功能包装对象。

装饰模式的优点在于,把类中的装饰功能从类中搬移出去,这样可以简化原有的类,有效的把类的核心职责装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑,即一个装饰功能可以给多个不同的类使用。

原文地址:https://www.cnblogs.com/CheeseZH/p/9374617.html

时间: 2024-08-30 00:19:32

[Python设计模式] 第6章 衣服搭配系统——装饰模式的相关文章

[Python设计模式] 第1章 计算器——简单工厂模式

写在前面的话 """ 读书的时候上过<设计模式>这一门课,当时使用的教材是程杰老师的<大话设计模式>,使用的语言是C#,学过课程之后初期深感面向对象思想的伟大,但是很少应用到实际开发中.后来我接触了Python,现在工作中用到最多的也是Python,或许是因为Python的便利性,我写的很多脚本/程序都还是面向过程编程,缺少面向对象的思想在里边.因此,我打算重读程杰老师的<大话设计模式>并用Python进行实践. ""&

[Python设计模式] 第18章 游戏角色备份——备忘录模式

github地址:https://github.com/cheesezh/python_design_patterns 题目 用代码模拟以下场景,一个游戏角色有生命力,攻击力,防御力等数据,在打Boss前后的数据值会发生变化,如果玩家挑战Boss失败,我们允许玩家可以将游戏数据恢复到与Boss决斗之前的状态. 基础版本 class GameRole(): def __init__(self): self.vitality = 0 self.attack = 0 self.defense = 0

[Python设计模式] 第17章 程序中的翻译官——适配器模式

github地址:https://github.com/cheesezh/python_design_patterns 适配器模式 适配器模式,将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作[DP]. 当系统的数据和行为都正确,但是接口不符时,我们应该考虑使用适配器模式,目的就是使控制范围之外的一个原有对象与某个接口匹配.适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况. class Targe

[Python设计模式] 第16章 上班,干活,下班,加班——状态模式

github地址:https://github.com/cheesezh/python_design_patterns 题目 用代码模拟一天的工作状态,上午状态好,中午想睡觉,下午渐恢复,加班苦煎熬. 基础版本--函数版 hour = 0 work_finished = False def write_program(): if hour < 12: print("当前时间: {} 点, 上午工作,精神百倍".format(hour)) elif hour < 13: pr

[Python设计模式] 第15章 如何兼容各种DB——抽象工厂模式

github地址:https://github.com/cheesezh/python_design_patterns 题目 如何让一个程序,可以灵活替换数据库? 基础版本 class User(): """ 用户类,模拟用户表,假设只有ID和name两个字段 """ def __init__(self): self.id = None self.name = None class SqlServerUser(): ""&qu

【读书笔记】设计模式第6章:行为型模式2

本文主要分析了中介者模式.观察者模式.备忘录模式.访问者模式.状态模式.解释器模式,介绍它们的定义.优缺点.使用场景,以及实例代码.为了深刻地理解设计模式,最重要的还是动手编写代码. 我参照书中的例程重新构想了一些更加生动.易于理解的例子,希望大家喜欢. 代码可以通过以下链接进行浏览: http://git.oschina.net/caipeichao/java-design-pattern 这些代码都经过编译运行,保证没有错误. 中介者模式 定义 也叫调停者模式 用一个中介对象来封装一系列同事

python 设计模式

介绍 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样.项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用

设计模式之序章-UML类图那点事儿

设计模式之序-UML类图那点事儿 序 打14年年底就像写那么一个系列,用于讲设计模式的,代码基于JAVA语言,最早接触设计模式是大一还是大二来着,那时候网上有人给推荐书,其中就有设计模式,当时给我推荐的书我还隐约记得,叫GoF的,书名是<Design Patterns: Elements of Reusable Object-Oriented Software>,也即<设计模式>,机械出版社的将其翻译为<设计模式-可复用面向对象软件的基础>.至于为什么叫做GoF,那时候

【读书笔记】设计模式第五章:行为型模式

本文主要分析了模板方法模式.命令模式.责任链模式.策略模式.迭代器模式,介绍它们的定义.优缺点.使用场景,以及实例代码.为了深刻地理解设计模式,最重要的还是动手编写代码. 我参照书中的例程重新构想了一些更加生动.易于理解的例子,希望大家喜欢. 代码可以通过以下链接进行浏览: http://git.oschina.net/caipeichao/java-design-pattern 这些代码都经过编译运行,保证没有错误. 模板方法 定义 定义一个操作中的算法框架,而将一些步骤延迟到子类中 角色:抽