github地址:https://github.com/cheesezh/python_design_patterns

题目

设计一个控制台程序,可以给人搭配嘻哈风格(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恤,垮裤的人类穿上运动鞋

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

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

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

  1. [Python设计模式] 第21章 计划生育——单例模式

    github地址:https://github.com/cheesezh/python_design_patterns 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式 ...

  2. [Python设计模式] 第22章 手机型号&软件版本——桥接模式

    github地址:https://github.com/cheesezh/python_design_patterns 紧耦合程序演化 题目1 编程模拟以下情景,有一个N品牌手机,在上边玩一个小游戏. ...

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

    github地址:https://github.com/cheesezh/python_design_patterns 写在前面的话 """ 读书的时候上过<设计模 ...

  4. [Python设计模式] 第28章 男人和女人——访问者模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目 用程序模拟以下不同情况: 男人成功时,背后多半有一个伟大的女人: 女人成功 ...

  5. [Python设计模式] 第26章 千人千面,内在共享——享元模式

    github地址:https://github.com/cheesezh/python_design_patterns 背景 有6个客户想做产品展示网站,其中3个想做成天猫商城那样的"电商风 ...

  6. [Python设计模式] 第25章 联合国维护世界和平——中介者模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目背景 联合国在世界上就是中介者的角色,各国之间的关系复杂,类似不同的对象和对 ...

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

    github地址:https://github.com/cheesezh/python_design_patterns 题目 用代码模拟以下场景,一个游戏角色有生命力,攻击力,防御力等数据,在打Bos ...

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

    github地址:https://github.com/cheesezh/python_design_patterns 适配器模式 适配器模式,将一个类的接口转换成客户希望的另外一个接口.Adapte ...

  9. [Python设计模式] 第14章 老板来了——观察者模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目 用程序模拟以下情景,在一个办公室里,当老板进门的时候,前台秘书就偷偷通知办 ...

随机推荐

  1. 性能测试三十九:Jprofiler分析CPU过高和响应时间长的问题

    使用Jprofiler监控分析案例 一.cpu负载过高:http://localhost:8080/PerfTeach/CpuTopServlet?id=1 cpu消耗高的可能原因1.使用了复杂的算法 ...

  2. python 全栈开发,Day134(爬虫系列之第1章-requests模块)

    一.爬虫系列之第1章-requests模块 爬虫简介 概述 近年来,随着网络应用的逐渐扩展和深入,如何高效的获取网上数据成为了无数公司和个人的追求,在大数据时代,谁掌握了更多的数据,谁就可以获得更高的 ...

  3. javafx点击鼠标出现弹窗,demo

    在学习javafx的过程中,不知道怎么出现一个弹窗,如,点击一个按钮出现一个修改信息的列表选项 终于在javafx文档示例中发现了类似的东西,记录一下,备忘package demo9_button; ...

  4. 《剑指offer》-左旋转字符串

    汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S="abc ...

  5. 【C++ Primer 第16章】1. 定义模板 (一)

    类模板 #include<iostream> #include<vector> #include<memory> using namespace std; temp ...

  6. poj 2406 求字符串中重复子串的个数

    Sample Input abcdaaaaababab.Sample Output 1 //1个abcd4 //4个a3 //3个ab #include<stdio.h> #include ...

  7. 自动化部署之gitlab权限管理--issue管理

    一.删除测试项目 先进入项目,选择编辑项目 二.拉取到最下方,移除项目 三 输入你要删除的项目名称 二 创建Group,User,Project 2.1 创建一个组,组名为java Group pat ...

  8. BZOJ1180 [CROATIAN2009]OTOCI LCT

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1180 本题和BZOJ2843一样. BZOJ2843 极地旅行社 LCT 题意概括 有n座岛 每座 ...

  9. Unity3d 之 理解Gameobject ,gameObject,Transform,transform的区别和关联

    Gameobject是一个类型,所有的游戏物件都是这个类型的对象. gameobject是一个对象, 就跟java里面的this一样, 指的是这个脚本所附着的游戏物件 public class Sho ...

  10. [洛谷P1731][NOI1999]生日蛋糕(dfs)(剪枝)

    典型的深搜+剪枝策略 我们采用可行性剪枝.上下界剪枝.优化搜索顺序剪枝.最优性剪枝的方面来帮助我们进行剪枝. 也许有人还不知道剪枝,那我就弱弱地为大家补习一下吧qwq: .优化搜索顺序: 在一些搜索问 ...