美文网首页
组合模式

组合模式

作者: 缓慢移动的蜗牛 | 来源:发表于2019-11-26 20:44 被阅读0次

    组合模式的定义

    定义:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有抑制性。

    通用类图如下:

    组合模式通用类图.png

    角色说明

    • Component抽象构件角色

      定义参加组合对象的公共方法和属性。可以定义一些默认的行为或者属性

    • Leaf叶子构件

      叶子对象,其下再也没有其他的分支,也就是遍历的最小单位。

    • Composite树枝构件

      树枝对象,它的作用是组合树枝节点和叶子节点形成一个树形结构。

    通用源码

    抽象构件

    public abstract class Component {
         //个体和整体都具有的共享
         public void doSomething(){
                 //编写业务逻辑
         }
    }
    

    树枝构件

    public class Composite extends Component {
         //构件容器
         private ArrayList<Component> componentArrayList = new ArrayList<Component>();
         //增加一个叶子构件或树枝构件
         public void add(Component component){
                 this.componentArrayList.add(component);
         }
         //删除一个叶子构件或树枝构件
         public void remove(Component component){
                 this.componentArrayList.remove(component);
         }
         //获得分支下的所有叶子构件和树枝构件
         public ArrayList&lt;Component&gt; getChildren(){
                 return this.componentArrayList;
         }
    }
    

    树叶构件

    public class Leaf extends Component {
         /*
          * 可以覆写父类方法
          * public void doSomething(){
          *
          * }
          */
    }
    

    场景类

    public class Client {
         public static void main(String[] args) {
                //创建一个根节点
                 Composite root = new Composite();
                 root.doSomething();
                 //创建一个树枝构件
                 Composite branch = new Composite();
                 //创建一个叶子节点
                 Leaf leaf = new Leaf();
                 //建立整体
                 root.add(branch);
                 branch.add(leaf);
         }
         //通过递归遍历树
         public static void display(Composite root){
                 for(Component c:root.getChildren()){
                      if(c instanceof Leaf){ //叶子节点
                              c.doSomething();
                      }else{ //树枝节点
                              display((Composite)c);
                      }
                 }
         }
    }
    

    组合模式的应用

    优点

    • 高层模块调用简单

      一个树形结构中所有的节点都是Component,局部和整体对调用者来说没有任何区别,也就是,高层模块不必关系自己处理的是单个对象还是整个组合结构,简化了高层模块的代码。

    • 节点自由增加

      使用了组合莫时候,如果想增加一个树枝节点、树叶节点都很容易。

    缺点

    组合模式有个非常明显的缺点,直接使用了实现类,这在面向接口编程上是很不恰当的,与依赖倒置原则冲突。

    使用场景

    • 维护和展示部分——整体关系的场景,如树形菜单、文件和文件夹管理。
    • 从一个整体中能够独立出部分模块或功能的场景。

    组合模式的两种实现

    组合模式有两种不同的实现:透明模式和安全模式

    透明模式:把用来组合使用的方法放到抽象类中,比如add()remove()以及getChildren()方法,不管叶子对象还是树枝都有相同的结构,通过判断getChildren()的返回值来确认是叶子节点还是树枝节点,如果处理不当,这个会在运行期出现问题,不建议

    安全模式:把树枝节点和树叶节点彻底分开,树枝节点单独拥有用来组合的方法,这种方法比较安全。

    安全组合模式的示例

    用组合模式来表示一个公司的组织架构

    类图如下:

    组合模式--公司组织架构类图.png

    抽象构件

    public abstract class Corp {
         //公司每个人都有名称
         private String name = "";
         //公司每个人都职位
         private String position = "";
         //公司每个人都有薪水
         private int salary =0;
         //记录当前节点的父节点
         private Corp parent = null;
         public Corp(String name,String position,int salary){
                 this.name = name;
                 this.position = position;
                 this.salary = salary;
         }
         //获得员工信息
         public String getInfo(){
                 String info = "";
                 info = "姓名:" + this.name;
                 info = info + "\t职位:"+ this.position;
                 info = info + "\t薪水:" + this.salary;
                 return info;
         }
         //设置父节点
         protected void setParent(Corp parent){
                 this.parent = parent;
         }
         //得到父节点
         public Corp getParent(){
                 return this.parent;
         }
    }
    

    树枝构件

    public class Branch extends Corp {
         //领导下边有哪些下级领导和小兵
         ArrayList<Corp> subordinateList = new ArrayList<Corp>();
         //构造函数是必需的
         public Branch(String name,String position,int salary){
                 super(name,position,salary);
         }
         //增加一个下属,可能是小头目,也可能是个小兵
         public void addSubordinate(Corp corp) {
                 corp.setParent(this); //设置父节点
                 this.subordinateList.add(corp);
         }
         //我有哪些下属
         public ArrayList<Corp> getSubordinate() {
                 return this.subordinateList;
         }
    }
    

    树叶节点

    public class Leaf extends Corp {
         //就写一个构造函数,这个是必需的
         public Leaf(String name,String position,int salary){
                 super(name,position,salary);
         }
    }
    

    场景类

    public class Client {
        public static void main(String[] args) {
            compositeCorpTree();
        }
    
        public static Branch compositeCorpTree(){
            Branch root = new Branch("王大麻子", "总经理", 100000);
    
            //产生三个部门经理,也是分枝节点
            Branch developDep = new Branch("刘", "研发部门经理", 2000);
            Branch salesDep = new Branch("王", "销售部经理", 3000);
            Branch financeDep = new Branch("高", "财务部经理", 4000);
            Branch firstDevGroup = new Branch("阳伞", "开发一组组长", 5);
            Branch secondDevGroup = new Branch("san", "开发二组组长", 5);
    
            //小兵
            Leaf a = new Leaf("a", "开发人员", 10);
            Leaf b = new Leaf("b", "开发人员", 10);
            Leaf c = new Leaf("c", "开发人员", 10);
            Leaf d = new Leaf("d", "开发人员", 10);
            Leaf e = new Leaf("e", "开发人员", 10);
            Leaf f = new Leaf("f", "开发人员", 10);
            Leaf g = new Leaf("g", "开发人员", 10);
            Leaf h = new Leaf("h", "销售人员", 10);
            Leaf i = new Leaf("i", "销售人员", 10);
            Leaf j = new Leaf("g", "财务人员", 10);
            Leaf k = new Leaf("k", "CEO秘书", 10);
            Leaf zhengLaoLiu = new Leaf("正老刘", "研发部副总", 1023);
    
    
            //组织关系
            root.addSubordinate(developDep);
            root.addSubordinate(salesDep);
            root.addSubordinate(financeDep);
            root.addSubordinate(k);
    
            developDep.addSubordinate(firstDevGroup);
            developDep.addSubordinate(secondDevGroup);
            developDep.addSubordinate(zhengLaoLiu);
            firstDevGroup.addSubordinate(a);
            firstDevGroup.addSubordinate(b);
            firstDevGroup.addSubordinate(c);
            secondDevGroup.addSubordinate(d);
            secondDevGroup.addSubordinate(e);
            secondDevGroup.addSubordinate(g);
    
            salesDep.addSubordinate(h);
            salesDep.addSubordinate(i);
    
            financeDep.addSubordinate(j);
    
            System.out.println(root.getInfo());
    
            //打印整个树形
            getAllSubordinateInfo(root.getSubordinate());
    
            return root;
        }
    
        private static void getAllSubordinateInfo(List<Corp> subordinateList){
            int length = subordinateList.size();
            for (int i = 0; i < length; i++) {
                Corp o = subordinateList.get(i);
                System.out.println(o.getInfo());
                if (o instanceof Branch) {
                    Branch branch = (Branch)o;
                    //递归调用其子节点
                    getAllSubordinateInfo(branch.getSubordinate());
                }
            }
        }
    }
    

    透明组合模式的示例

    类图如下:

    透明模式的组合模式.png

    抽象组件

    public abstract class Component {
        /**
         * 个体和整体都具有的共享
         */
        public abstract void doSomething();
    
        /**
         * 增加一个叶子构件或树枝构件
         * @param component
         */
        public abstract void add(Component component);
    
        /**
         * 删除一个叶子构件或树枝构件
         * @param component
         */
        public abstract void remove(Component component);
    
        /**
         * 获得分枝下的所有叶子构件或树枝构件
         * @return
         */
        public abstract List<Component> getChildren();
    }
    

    树枝

    public class Composite extends Component{
        List<Component> subordinateList = new ArrayList<>();
        @Override
        public void doSomething() {
    
        }
    
        @Override
        public void add(Component component) {
            this.subordinateList.add(component);
        }
    
        @Override
        public void remove(Component component) {
            this.subordinateList.remove(component);
        }
    
        @Override
        public List<Component> getChildren() {
            return this.subordinateList;
        }
    }
    

    树叶

    public class Leaf extends Component{
        @Override
        public void doSomething() {
    
        }
    
        @Deprecated
        @Override
        public void add(Component component) throws UnsupportedOperationException{
            throw new UnsupportedOperationException();
        }
    
        @Deprecated
        @Override
        public void remove(Component component) throws UnsupportedOperationException{
            throw new UnsupportedOperationException();
        }
    
        @Deprecated
        @Override
        public List<Component> getChildren() throws UnsupportedOperationException{
            throw new UnsupportedOperationException();
        }
    }
    

    相关文章

      网友评论

          本文标题:组合模式

          本文链接:https://www.haomeiwen.com/subject/nkgywctx.html