• 设计模式之(八)组合模式(COMPOSITE)


    初始印象

      在开发中存在很多整体和部分的关系,这个方式最大的体现就是树形结构。组合模式就是为了更好地解决这类业务场景的问题。先看下组合模式的定义:

      将对象组合成树形结构以表示“整体—部分”的层次关系。组合模式使得用户对单个对象和组合对象的使用具有一致性。从定义中可以看出来组合二模式主要有两点;  

        1、整体 - 部分 之间业务结构用树形表示。

        2、让组合对象和各个对象的使用具有一致性。

      

            整体和部分的结构在生活中太广泛了,比如国家行政级别  中国 ,***省,**市 。学校管级别、公司管理组织机构等,下面以公司组织机构为例,来看看组合模式。

        

       根据这个公司组织结构的图片,来引进助兴结构的专业名词:总经理称之为 root 根节点,财务经理、技术经理、开发组长称之为 树枝节点(branch),财务专员、秘书称之为 叶子节点(leaf)。

            而具体到代码的实现层面就是,组合模式的核心关键就是把这三个对象实现相同的接口,不管是在组件过程,还是后面的遍历,所有的节点都用相同的接口,使得对树形结构的操作更加方便。

      接着介绍组合模式的组成元素

    • Component:组合部件,为的是给 root、branch、leaf 不同的节点提供统一的接口。
    • Composite:复合节点,就是实现 root、branch 的节点,也叫容器节点。
    • Leaf : 叶子节点,不能再有下属节点。也叫简单节点。

    应用例子

         接下来吧上图中例子实现以下,能够更直观了解组合模式

    // 相当于是 Component
    public abstract class  Zhiwei {
        protected String name;
        protected String position;
        protected float salary;
        
        public Zhiwei(String name,String position,float salary){
            this.name = name;
            this.position = position;
            this.salary = salary;
        }
        
        public abstract void addChild(Zhiwei zhiwei);
        
        public abstract void removeChild(Zhiwei zhiwei);
        
        public abstract void display(String empty);
        
    }
    
    //相当于是 Composite
    public class LingDao extends Zhiwei {
    
        private ArrayList<Zhiwei> children = new ArrayList<Zhiwei>();
        
        public LingDao(String name,String position,float salary){
            super(name,position,salary);
        }
        
        @Override
        public  void addChild(Zhiwei zhiwei) {
            // TODO Auto-generated method stub
            children.add(zhiwei);
        }
    
        @Override
        public void removeChild(Zhiwei zhiwei) {
            // TODO Auto-generated method stub
            
            children.remove(zhiwei);
        }
    
        @Override
        public void display(String empty) {
            // TODO Auto-generated method stub
            System.out.println(empty+"职位:"+this.position+" 姓名:"+this.name+" 薪水:"+this.salary);
            for (Zhiwei zhiwei : children) {
                zhiwei.display(empty+"    ");
            }
            
        }
    
    }
    
    //普通职员
    public class Leaf extends Zhiwei {
    
        public Leaf(String name, String position, float salary) {
            super(name, position, salary);
            
            // TODO Auto-generated constructor stub
        }
    
        @Override
        public void addChild(Zhiwei zhiwei) {
            // TODO Auto-generated method stub
            System.out.println("cannot add zhiwei to leaf");
        }
    
        @Override
        public void removeChild(Zhiwei zhiwei) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void display(String empty) {
            // TODO Auto-generated method stub
            System.out.println(empty+"职位:"+this.position+" 姓名:"+this.name+" 薪水:"+this.salary);
        }
    }
    
    //客户端
    public class Client {
        public static void main(String[] args) {
            Zhiwei leader = new LingDao("张无忌","总经理",100000);
            
            Zhiwei manager = new LingDao("杨逍", "技术经理", 50000);
            Zhiwei managerB = new LingDao("范瑶","财务经理",50000);
            Zhiwei managerC = new LingDao("吴劲草","技术组长",20000);
            
            Zhiwei Employee = new LingDao("小昭","秘书",8000);
            
            Zhiwei EmployeeA = new LingDao("天字门","财务A",5000);
            Zhiwei EmployeeX = new LingDao("地字门","财务B",5200);
            Zhiwei EmployeeC = new LingDao("风字门","开发A",8800);
            Zhiwei EmployeeD = new LingDao("雷字门","开发B",8400);
            
            leader.addChild(manager);
            leader.addChild(managerB);
            leader.addChild(Employee);
            
            manager.addChild(managerC);
            manager.addChild(EmployeeC);
            
            managerC.addChild(EmployeeD);
            
            leader.display("");
        }
    }
    
    /********************控制台************************/
    
    - 职位:总经理 姓名:张无忌 薪水:100000.0
         - 职位:技术经理 姓名:杨逍 薪水:50000.0
              - 职位:技术组长 姓名:吴劲草 薪水:20000.0
                   - 职位:开发B 职位:雷字门 薪水:8400.0
              - 职位:开发A 姓名:风字门 薪水:8800.0
         - 职位:财务经理 姓名:范瑶 薪水:50000.0
              - 职位:财务A 姓名:风字门 薪水:5000.0
              - 职位:财务B 姓名:地字门 薪水:5200.0
         - 职位:秘书 姓名:小昭 薪水:8000.0

      通过这个例子可以看出来,不同级别的节点通过同一接口在客户端试用是非常方便的,调用的时候不用管他代表的是什么节点。因为能够同一试用。只是在 leaf 级别的节点中,考虑 addChild 、removeChild 给出错误提示即可。

    对模式的分析

      我们进一步来分析组合模式的应用场景,除了在很明显的树形结构业务中用,在发挥我们的发散能力,应该能够想到,只要拥有父子关系的场景中都是可以用的比如窗体打开的父子窗口、各种单位的人事制度的组织结构、文件管理系统、软件系统的树形结构导航。

      在思考了组合模式的应用场景后,在考虑下组合模式的优势:

           1、定义了实现不同层次的对象的统一接口,对象行为更具有一致性。使得客户端调用比较简单。

      2、实现了整个业务场景的类层级的所属关系,通过类里面的 list 来实现。

      3、类实现更具一般性,使得代码更具有可扩展性。主要表现在新定义的 composite 和 leaf 继承了统一的操作接口,客户端就不用改变。

    小结

      组合模式应用场景是具有父子结构的场景,典型的就是树形结构。模式的本质就是对不同级别的节点对象引入统一的接口,对不同级别对象调用、操作具有了一致性。

  • 相关阅读:
    用几何画板画三星状图形的方法有哪些
    ChemDraw 15.1 Pro插入阿尔法可以这样做
    用MathType编辑异或与非符号有什么方法
    整合Thinkphp数据库基本操作CURD,界面datagrid采用EasyUi的Demo
    可编辑表格
    jQuery一步一步实现跨浏览器的可编辑表格,支持IE、Firefox、Safari、
    jfinal 使用类里的方法
    左右值无限分类实现算法
    PHP递归实现无限级分类
    ThinkPHP自动填充实现无限级分类的方法
  • 原文地址:https://www.cnblogs.com/pengweiqiang/p/11030156.html
Copyright © 2020-2023  润新知