• [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()
        
    
    组织架构图
    - 北京总公司
    --- 总公司人力资源部
    --- 总公司财务部
    --- 上海华东分公司
    ----- 华东分公司人力资源部
    ----- 华东分公司财务部
    ----- 南京办事处
    ------- 南京办事处人力资源部
    ------- 南京办事处财务部
    ----- 杭州办事处
    ------- 杭州办事处人力资源部
    ------- 杭州办事处财务部
    履行职责
    总公司人力资源部负责员工招聘。
    总公司财务部负责财务收支。
    华东分公司人力资源部负责员工招聘。
    华东分公司财务部负责财务收支。
    南京办事处人力资源部负责员工招聘。
    南京办事处财务部负责财务收支。
    杭州办事处人力资源部负责员工招聘。
    杭州办事处财务部负责财务收支。
    

    点评

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

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

  • 相关阅读:
    算法学习笔记: 珂朵莉树
    算法学习笔记:2SAT
    0x62 图论最小生成树
    Codeforces Round #632 (Div. 2) C. Eugene and an array(尺取法/前缀和)
    BZOJ1912 异象石(LCA/DFS序/set)
    (六1)Firefox插件安装
    (六2)八种定位方式为了查找元素
    (六3)从查找元素到操作元素
    【OSI】网络协议模型
    读《Wireshark网络分析就这么简单》读书笔记
  • 原文地址:https://www.cnblogs.com/CheeseZH/p/9462244.html
Copyright © 2020-2023  润新知