[Python设计模式] 第19章 分公司=部门?——组合模式
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()
组织架构图 - 北京总公司 --- 总公司人力资源部 --- 总公司财务部 --- 上海华东分公司 ----- 华东分公司人力资源部 ----- 华东分公司财务部 ----- 南京办事处 ------- 南京办事处人力资源部 ------- 南京办事处财务部 ----- 杭州办事处 ------- 杭州办事处人力资源部 ------- 杭州办事处财务部 履行职责 总公司人力资源部负责员工招聘。 总公司财务部负责财务收支。 华东分公司人力资源部负责员工招聘。 华东分公司财务部负责财务收支。 南京办事处人力资源部负责员工招聘。 南京办事处财务部负责财务收支。 杭州办事处人力资源部负责员工招聘。 杭州办事处财务部负责财务收支。
点评
组合模式定义了包含人力资源部和财务部这些基本对象和分公司,办事处等组合对象的类层次结构。基本对象可以被组合成共复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户端代码中,任何用到基本对象的地方都可以使用组合对象了。用户不用关心到底是处理一个叶子节点还是处理一个组合组件,也用不着为定义组合而写一些选择判断语句。
简单的说,组合模式让客户可以一致地使用组合结构和单个对象。
- 设计模式:19 分公司=一部门_组合模式
- 【设计模式】分公司是一个部门? ---- 组合模式
- 第19章 分公司=一部门------组合模式
- 设计模式-组合模式-composite-python??
- 《大话设计模式》--分公司=一部门--组合模式<Composite>(19)
- 分公司=一部门——组合模式
- python设计模式(组合模式)
- Python的结构型设计模式之组合模式
- python设计模式之组合模式
- python设计模式之组合模式
- 大话设计模式-第19章 分公司=一部分--组合模式
- 分公司=一部门——组合模式
- 设计模式十二(组合模式,python语言实现)
- 大话设计模式十九:组合模式(分公司 = 一部门)
- Python 设计模式——用模式改善软件设计
- 设计模式之组合模式
- 编程经常使用设计模式具体解释--(中篇)(适配器、装饰、代理、外观、桥接、组合、享元)
- 设计模式中类的关系之组合关系(Composition)
- [C++设计模式] composite 组合模式
- java设计模式之组合模式