大话设计模式:第19章 组合模式

第19章:组合模式

组合模式

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

在这里插入图片描述

组合模式适合处理整体与部分可以被一致对待的问题。

Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component的子部件。

在这里插入图片描述

Leaf在组合中表示叶节点对象,叶节点没有子节点。

在这里插入图片描述

Composite定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,比如增加Add和删除Remove

在这里插入图片描述

客户端代码,能通过Component接口操作组合部件的对象。

在这里插入图片描述

结果显示

在这里插入图片描述

透明方式与安全方式

透明方式Leaf类不可以再长分枝,但Leaf类也有AddRemove方法,即在Component类中声明所有用来管理子对象的方法,这样实现Component接口的所有子类都具备了AddRemove等方法。这样做的好处是叶节点枝节点对于外界没有区别,它们具备完全一致的行为接口。但问题是,Leaf类本身不具备AddRemove方法的功能,所以实现它没有意义。

安全方式:在Component接口中不声明AddRemove方法,则子类Leaf无需实现AddRemove方法,在子类Composite中声明所有用来管理子类对象的方法。不过由于不够透明,所以树叶和树枝类将不具有相同的接口,客户端的调用需要做相应的判断。

组合模式的使用

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

例:ASP.NETTreeView控件、自定义控件(把一些基本的控件组合起来,通过编程写成个定制的控件,比如用两个文本框和一个按钮可以定义的登录框控件)。

所有的Web控件的基类都是System.Web.UI.Control,而Control基类中就有AddRemove方法,这就是典型的组合模式的应用。

组合模式的好处

  1. 组合模式定义了包含基本对象和组合对象的类层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象。

  2. 用户不用关心到底是处理一个叶节点还是处理一个组合组件,也就不用为定义组合而写一些选择判断语句,即,组合模式让客户可以一致地使用组合结构和单个对象。

组合模式示例

任务:公司管理系统

在这里插入图片描述

from abc import ABC, abstractmethod
from typing import Text
class Company(ABC):
    """
    公司类(抽象类或接口)
    """
    def __init__(self, name: Text):
        self._name = name
    
    @abstractmethod
    def add(self, c: object) -> None:
        """
        增加
        """
        pass
    @abstractmethod
    def remove(self, c: object) -> None:
        """
        移除
        """
        pass
    @abstractmethod
    def display(self, depth: int) -> None:
        """
        显示
        """
        pass
    @abstractmethod
    def line_of_duty(self) -> None:
        """
        履行职责
        """
        pass
    
class ConcreteCompany(Company):
    """
    具体公司类(实现接口树枝节点)
    """
    
    def __init__(self, name: Text):
        super(ConcreteCompany, self).__init__(name)
        self.__children = []
        
    def add(self, c: Company) -> None:
        self.__children.append(c)
        
    def remove(self, c: Company) -> None:
        self.__children.remove(c)
        
    def display(self, depth: int) -> None:
        print("-" * depth, self._name)
        for component in self.__children:
            component.display(depth + 2)
            
    def line_of_duty(self) -> None:
        for component in self.__children:
            component.line_of_duty()
            
class HRDepartment(Company):
    """
    人力资源部与财务部类树叶节点
    """
    
    def __init__(self, name: Text):
        super(HRDepartment, self).__init__(name)
        
    def add(self, c: Company) -> None:
        pass
        
    def remove(self, c: Company) -> None:
        pass
        
    def display(self, depth: int) -> None:
        print("-" * depth, self._name)
        
    def line_of_duty(self) -> None:
        print(self._name, "员工招聘培训管理")
        
class FinanceDepartment(Company):
    """
    人力资源部与财务部类树叶节点
    """
    
    def __init__(self, name: Text):
        super(FinanceDepartment, self).__init__(name)
        
    def add(self, c: Company) -> None:
        pass
        
    def remove(self, c: Company) -> None:
        pass
        
    def display(self, depth: int) -> None:
        print("-" * depth, self._name)
        
    def line_of_duty(self) -> None:
        print(self._name, "公司财务收支管理")
        
# 客户端调用

if __name__ == "__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()
**结构图**
- 北京总公司
--- 总公司人力资源部
--- 总公司财务部
--- 上海华东分公司
----- 华东分公司人力资源部
----- 华东分公司财务部
----- 南京办事处
------- 南京办事处人力资源部
------- 南京办事处财务部
----- 杭州办事处
------- 杭州办事处人力资源部
------- 杭州办事处财务部
**职责**
总公司人力资源部 员工招聘培训管理
总公司财务部 公司财务收支管理
华东分公司人力资源部 员工招聘培训管理
华东分公司财务部 公司财务收支管理
南京办事处人力资源部 员工招聘培训管理
南京办事处财务部 公司财务收支管理
杭州办事处人力资源部 员工招聘培训管理
杭州办事处财务部 公司财务收支管理

猜你喜欢

转载自blog.csdn.net/zhaoyin214/article/details/105980517
今日推荐