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

    点评

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

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

  • 相关阅读:
    LeetCode OJ 107. Binary Tree Level Order Traversal II
    LeetCode OJ 116. Populating Next Right Pointers in Each Node
    LeetCode OJ 108. Convert Sorted Array to Binary Search Tree
    LeetCode OJ 105. Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode OJ 98. Validate Binary Search Tree
    老程序员解Bug的通用套路
    转载 四年努力,梦归阿里,和大家聊聊成长感悟
    转载面试感悟----一名3年工作经验的程序员应该具备的技能
    Web Service和Servlet的区别
    关于spring xml文件中的xmlns,xsi:schemaLocation
  • 原文地址:https://www.cnblogs.com/CheeseZH/p/9462244.html
Copyright © 2011-2022 走看看