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

组合模式

组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和对组合对象的使用具有一致性[DP]。

from abc import ABCMeta, abstractmethod

class Component():
"""
Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。
声明一个接口用于访问和管理Component的子部件。
"""
__metaclass__ = ABCMeta def __init__(self, name):
self.name = name @abstractmethod
def add(self, c):
"""
通常用add来增加树枝或树叶
"""
pass @abstractmethod
def remove(self, c):
"""
通常用remove来删除树枝或树叶
"""
pass @abstractmethod
def display(self, depth):
pass class Leaf(Component):
"""
叶子节点
"""
def add(self, c):
print("叶子节点无法添加子节点") def remove(self, c):
print("叶子节点无法删除子节点") def display(self, depth):
print("-"*depth, self.name) class Composite(Component):
"""
子部件节点
"""
def __init__(self, name):
super().__init__(name)
self.children = [] def add(self, c):
self.children.append(c) def remove(self, c):
self.children.remove(c) def display(self, depth):
print("-"*depth, self.name)
for c in self.children:
c.display(depth+2) def main():
root = Composite("root")
root.add(Leaf("Leaf A"))
root.add(Leaf("Leaf B")) comp = Composite("Composite X")
comp.add(Leaf("Leaf XA"))
comp.add(Leaf("Leaf XB")) root.add(comp) comp2 = Composite("Composite XY")
comp2.add(Leaf("Leaf XYA"))
comp2.add(Leaf("Leaf XYB")) comp.add(comp2) root.add(Leaf("Leaf C")) leaf_d = Leaf("Leaf D")
root.add(leaf_d)
root.remove(leaf_d) root.display(1) main()
- root
--- Leaf A
--- Leaf B
--- Composite X
----- Leaf XA
----- Leaf XB
----- Composite XY
------- Leaf XYA
------- Leaf XYB
--- Leaf C

透明方式与安全方式

Leaf类中也有Add和Reomve,但是树叶不可以再长分枝。这种方式叫做透明方式,也就是说再Component中声明所有用来管理子对象的方法,其中包括add,remove等。这样Component抽象类的所有子类都具备了add和remove。这样的好处在于叶子节点和分枝节点对于外界没有区别,它们具备完全一致的行为接口。但是问题也比较明显,因为Leaf类本身不具备add和remove等功能,所以实现它是没有意义的。

另一种是安全方式,也就是在Component接口中不去声明add和remove方法,那么子类Leaf也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法,这样做就不会出现刚才提到的问题,不过由于不透明,所以树叶和树枝类将有不同的接口,客户端调用需要做相应的判断,带来了不便。

何时使用组合模式

当需求中是体现部分与整体层次的结构时,以及希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。

题目

使用组合模式,模拟公司管理系统。

from abc import ABCMeta, abstractmethod

class Company():
"""
抽象公司类
"""
__metaclass__ = ABCMeta def __init__(self, name):
self.name = name @abstractmethod
def add(self, c):
"""
通常用add来增加树枝或树叶
"""
pass @abstractmethod
def remove(self, c):
"""
通常用remove来删除树枝或树叶
"""
pass @abstractmethod
def display(self, depth):
pass @abstractmethod
def line_of_duty(self):
pass class ConcreteCompany(Company):
"""
具体公司类
"""
def __init__(self, name):
super().__init__(name)
self.children = [] def add(self, c):
self.children.append(c) def remove(self, c):
self.children.remove(c) def display(self, depth):
print("-"*depth, self.name)
for c in self.children:
c.display(depth+2) def line_of_duty(self):
for c in self.children:
c.line_of_duty() class HRDepartment(Company):
"""
人力资源部
"""
def add(self, c):
pass def remove(self, c):
pass def display(self, depth):
print("-"*depth, self.name) def line_of_duty(self):
print("{}负责员工招聘。".format(self.name)) class FinanceDepartment(Company):
"""
财务部
"""
def add(self, c):
pass def remove(self, c):
pass def display(self, depth):
print("-"*depth, self.name) def line_of_duty(self):
print("{}负责财务收支。".format(self.name)) def main():
root = ConcreteCompany("北京总公司")
root.add(HRDepartment("总公司人力资源部"))
root.add(FinanceDepartment("总公司财务部")) comp = ConcreteCompany("上海华东分公司")
comp.add(HRDepartment("华东分公司人力资源部"))
comp.add(FinanceDepartment("华东分公司财务部"))
root.add(comp) comp1 = ConcreteCompany("南京办事处")
comp1.add(HRDepartment("南京办事处人力资源部"))
comp1.add(FinanceDepartment("南京办事处财务部"))
comp.add(comp1) comp2 = ConcreteCompany("杭州办事处")
comp2.add(HRDepartment("杭州办事处人力资源部"))
comp2.add(FinanceDepartment("杭州办事处财务部"))
comp.add(comp2) print("组织架构图")
root.display(1) print("履行职责")
root.line_of_duty() main()
组织架构图
- 北京总公司
--- 总公司人力资源部
--- 总公司财务部
--- 上海华东分公司
----- 华东分公司人力资源部
----- 华东分公司财务部
----- 南京办事处
------- 南京办事处人力资源部
------- 南京办事处财务部
----- 杭州办事处
------- 杭州办事处人力资源部
------- 杭州办事处财务部
履行职责
总公司人力资源部负责员工招聘。
总公司财务部负责财务收支。
华东分公司人力资源部负责员工招聘。
华东分公司财务部负责财务收支。
南京办事处人力资源部负责员工招聘。
南京办事处财务部负责财务收支。
杭州办事处人力资源部负责员工招聘。
杭州办事处财务部负责财务收支。

点评

组合模式定义了包含人力资源部和财务部这些基本对象和分公司,办事处等组合对象的类层次结构。基本对象可以被组合成共复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户端代码中,任何用到基本对象的地方都可以使用组合对象了。用户不用关心到底是处理一个叶子节点还是处理一个组合组件,也用不着为定义组合而写一些选择判断语句。

简单的说,组合模式让客户可以一致地使用组合结构和单个对象。

[Python设计模式] 第19章 分公司=部门?——组合模式的更多相关文章

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

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

  2. [Python设计模式] 第13章 造小人——建造者模式

    github地址:https://github.com/cheesezh/python_design_patterns 题目1 用程序模拟一个画小人的过程,要求小人要有头,身子,左手,右手,左脚,右脚 ...

  3. javascript设计模式(张容铭) 第14章 超值午餐-组合模式 学习笔记

    JS 组合模式更常用于创建表单上,比如注册页面可能有不同的表单提交模块.对于这些需求我们只需要有基本的个体,然后通过一定的组合即可实现,比如下面这个页面样式(如图14-2所示),我们来用组合模式实现. ...

  4. 设计模式(九):Composite组合模式 -- 结构型模式

    1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面. 例子1:就是多级树形菜单. 例子2:文件和文件夹目录 2.问题 我们可以使用简单的对象组合成复杂的对象,而这个复杂对 ...

  5. 【设计模式】学习笔记13:组合模式(Composite)

    本文出自   http://blog.csdn.net/shuangde800 认识组合模式 上一篇中,我们可以用迭代器来实现遍历一个集合(数组,ArrayList, Vector, HashTabl ...

  6. Java设计模式偷跑系列(十二)组合模式建模和实现

    转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/39828653 组合模式(Composite):组合模式有时又叫部分-总体模式.将对象组合成 ...

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

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

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

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

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

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

随机推荐

  1. Codeforces 316G3 Good Substrings 字符串 SAM

    原文链接http://www.cnblogs.com/zhouzhendong/p/9010851.html 题目传送门 - Codeforces 316G3 题意 给定一个母串$s$,问母串$s$有 ...

  2. mac 命令操作

    内核空间和用户空间 x86架构中将内核地址空间划分三部分:ZONE_DMA.ZONE_NORMAL和 ZONE_HIGHMEM. 自动加载(开机自动启动服务) ln -sfv /usr/local/o ...

  3. Raspberry Camera详解+picamera库+Opencv控制

    使用树莓派的摄像头,将树莓派自身提供的picamera的API数据转换为Python Oencv可用图像数据: # import the necessary packages from picamer ...

  4. setTimeout/setInterval,属性、连续动画、倒计时的分析

    setTimeout.setInterval环境应用和使用场景 说明:setTimeout属于超时调用, setInterval 属于间隔调用 1,setTimeout超时的使用介绍: var set ...

  5. Codeforces 1095F Make It Connected 【MST】

    <题目链接> 题目大意: 给定一张n个顶点(每个顶点有点权)的无向图,并且给出边权为wi的m条边,顶点u和顶点v直接如果建边,边权为a_u + a_v,求图连通的最小边权和. 解题分析: ...

  6. jupyter notebook不能选择虚拟环境的解决方法

    今天使用dlib没有py37版本,因此创建了Version_36虚拟环境.但jupyter notebook默认的内核找不到新建的虚拟环境,解决方法是需要安装两个包: × ipykernel × nb ...

  7. ORA-01000

    A ResultSet object is automatically closed by the Statement object that generated it when that State ...

  8. C#数组和集合整理

    写起来还是有些勉强的,还有很多用法没有完全理解,只整理了一些基本点. Array ArrayList List Hashtable Dictionary Stack Queue Array 也就是数组 ...

  9. PAT (Advanced Level) Practise 1004 解题报告

    GitHub markdownPDF 问题描述 解题思路 代码 提交记录 问题描述 Counting Leaves (30) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 1600 ...

  10. Java并发编程:volatile关键字解析zz

    volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...