[Python设计模式] 第6章 衣服搭配系统——装饰模式
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章 衣服搭配系统——装饰模式的更多相关文章
- [Python设计模式] 第21章 计划生育——单例模式
github地址:https://github.com/cheesezh/python_design_patterns 单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式 ...
- [Python设计模式] 第22章 手机型号&软件版本——桥接模式
github地址:https://github.com/cheesezh/python_design_patterns 紧耦合程序演化 题目1 编程模拟以下情景,有一个N品牌手机,在上边玩一个小游戏. ...
- [Python设计模式] 第1章 计算器——简单工厂模式
github地址:https://github.com/cheesezh/python_design_patterns 写在前面的话 """ 读书的时候上过<设计模 ...
- [Python设计模式] 第28章 男人和女人——访问者模式
github地址:https://github.com/cheesezh/python_design_patterns 题目 用程序模拟以下不同情况: 男人成功时,背后多半有一个伟大的女人: 女人成功 ...
- [Python设计模式] 第26章 千人千面,内在共享——享元模式
github地址:https://github.com/cheesezh/python_design_patterns 背景 有6个客户想做产品展示网站,其中3个想做成天猫商城那样的"电商风 ...
- [Python设计模式] 第25章 联合国维护世界和平——中介者模式
github地址:https://github.com/cheesezh/python_design_patterns 题目背景 联合国在世界上就是中介者的角色,各国之间的关系复杂,类似不同的对象和对 ...
- [Python设计模式] 第18章 游戏角色备份——备忘录模式
github地址:https://github.com/cheesezh/python_design_patterns 题目 用代码模拟以下场景,一个游戏角色有生命力,攻击力,防御力等数据,在打Bos ...
- [Python设计模式] 第17章 程序中的翻译官——适配器模式
github地址:https://github.com/cheesezh/python_design_patterns 适配器模式 适配器模式,将一个类的接口转换成客户希望的另外一个接口.Adapte ...
- [Python设计模式] 第14章 老板来了——观察者模式
github地址:https://github.com/cheesezh/python_design_patterns 题目 用程序模拟以下情景,在一个办公室里,当老板进门的时候,前台秘书就偷偷通知办 ...
随机推荐
- bootstrap——辅助类和响应式工具类
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- ubuntu ufw防火墙软件的配置入门
顺便,一条龙作完安全吧. ufw的使用,是比iptables简单.但只能作简单的事儿,更改简单的netfilter里的iptable里的记录.难点的,可能还是得iptables原生命令. 自打2.4版 ...
- 【读书笔记】《深入浅出Webpack》
Webpack版本 分析版本为3.6.0 4.0为最近升级的版本,与之前版本变化较大,编译输出的文件与3.0版本会不一致,目前项目中使用的版本3.0版本,所以基于3.0版本进行分析学习. Webpac ...
- Codeforces 327E Axis Walking 状压dp
这题真的有2500分吗... 难以置信... #include<bits/stdc++.h> #define LL long long #define fi first #define s ...
- PHP 扩展 MongoDB
打开phpinfo 查看 nts(非线程) 还是 ts (线程),操作位数: 下载对应的版本的php_mongodb.dll 文件 下载链接: pecl mangodb下载 把文件解压出来 php_m ...
- 外部函数/external
定义在moodle/lib/externallib.php 概观 外部函数API允许您创建可由外部程序(如Web服务API)访问的完全参数化的方法. 外部函数位于externallib.php文件中. ...
- Burp Suite之爬网模块(二)
Spider功能 Burp Spider爬网介绍 Burp Spider 是一个映射 web 应用程序的工具.它使用多种智能技术对一个应用程序的内容和功能进行全面的清查. 通过跟踪 HTML 和 Ja ...
- Flutter常用组件(Widget)解析-ListView
一个可滚动的列表组件 不管在哪,列表组件都尤为重要和常用. 首先来看个例子: import 'package:flutter/material.dart'; void main () => ru ...
- 不一样的go语言-构建系统与构件系统
前言 代码的最后一步是构建成计算机可识别的二进制数据,然后才得以在计算机上运行.如果你曾经写过有点规模(至少数十个以上独立的源文件,且需要依赖第三方包)C语言项目,必定对C语言项目的构建过程印象深 ...
- js数据结构之hash散列的详细实现方法
hash散列中需要确定key和value的唯一确定关系. hash散列便于快速的插入删除和修改,不便于查找最大值等其他操作 以下为字符和数字的hash散列: function HashTable () ...