ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

设计模式之禅-组合模式

2021-02-22 18:29:26  阅读:246  来源: 互联网

标签:Leaf 之禅 组合 Branch addSubordinate new 设计模式 public String


目录

组合模式

例子

公司管理结构图。

在这里插入图片描述

public class Corp {
    private String name = "";
    private String position = "";
    private int salary = 0;

    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;
    }
}
public class Branch extends Corp{
    ArrayList<Corp> subordinateList = new ArrayList<>();
    public Branch(String name, String position, int salary) {
        super(name, position, salary);
    }
    public void addSubordinate(Corp corp){
        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) {
        Branch ceo = compositeCorpTree();
        System.out.println(getTreeInfo(ceo));

    }

    public static Branch compositeCorpTree() {
        Branch root = new Branch("王大麻子", "总经理", 100000);
        Branch developDep = new Branch("刘大瘸子", "研发部门经理", 10000);
        Branch salesDep = new Branch("马二拐子", "销售部门经理", 20000);
        Branch financeDep = new Branch("赵三驼子", "财务部经理", 30000);
        //再把三个小组长产生出来
        Branch firstDevGroup = new Branch("杨三乜斜", "开发一组组长", 5000);
        Branch secondDevGroup = new Branch("吴大棒槌", "开发二组组长", 6000);
        //把所有的小兵都产生出来
        Leaf a = new Leaf("a", "开发人员", 2000);
        Leaf b = new Leaf("b", "开发人员", 2000);
        Leaf c = new Leaf("c", "开发人员", 2000);
        Leaf d = new Leaf("d", "开发人员", 2000);
        Leaf e = new Leaf("e", "开发人员", 2000);
        Leaf f = new Leaf("f", "开发人员", 2000);
        Leaf g = new Leaf("g", "开发人员", 2000);
        Leaf h = new Leaf("h", "销售人员", 5000);
        Leaf i = new Leaf("i", "销售人员", 4000);
        Leaf j = new Leaf("j", "财务人员", 5000);
        Leaf k = new Leaf("k", "CEO秘书", 8000);
        Leaf zhengLaoLiu = new Leaf("郑老六", "研发部副经理", 20000);
        root.addSubordinate(k);
        root.addSubordinate(developDep);
        root.addSubordinate(salesDep);
        root.addSubordinate(financeDep);
        developDep.addSubordinate(zhengLaoLiu);
        developDep.addSubordinate(firstDevGroup);
        developDep.addSubordinate(secondDevGroup);
        firstDevGroup.addSubordinate(a);
        firstDevGroup.addSubordinate(b);
        firstDevGroup.addSubordinate(c);
        secondDevGroup.addSubordinate(d);
        secondDevGroup.addSubordinate(e);
        secondDevGroup.addSubordinate(f);
        salesDep.addSubordinate(h);
        salesDep.addSubordinate(i);
        financeDep.addSubordinate(j);
        return root;
    }

    public static String getTreeInfo(Branch root) {
        ArrayList<Corp> subordinateList = root.subordinateList;
        StringBuilder info = new StringBuilder();
        for (Corp s : subordinateList) {
            if (s instanceof Leaf) {
                info.append(s.getInfo()).append("\n");
            } else {
                info.append(s.getInfo()).append("\n").append(getTreeInfo((Branch) s));
            }
        }
        return info.toString();
    }
}

定义

将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
在这里插入图片描述

  • Component抽象构件角色
    定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性,比如我们例子中的getInfo就封装到了抽象类中。
  • Leaf叶子构件
    叶子对象,其下再也没有其他的分支,也就是遍历的最小单位。
  • Composite树枝构件
    树枝对象,它的作用是组合树枝节点和叶子节点形成一个树形结构。
public abstract class Component {
    void doSomething(){
        // 业务
    }
}
public class Composite extends Component {
    private final ArrayList<Component> componentArrayList = new ArrayList<>();

    public void add(Component component) {
        this.componentArrayList.add(component);
    }

    public void remove(Component component) {
        this.componentArrayList.remove(component);
    }

    public ArrayList<Component> getChildren() {
        return this.componentArrayList;
    }
}
public class Leaf extends Component{

}
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);
    }

    /**
     * 通过递归遍历树
     * @param root
     */
    public static void display(Composite root) {
        for (Component c : root.getChildren()) {
            if (c instanceof Leaf) {
                //叶子节点
                c.doSomething();
            } else { //树枝节点
                display((Composite) c);
            }
        }
    }
}

优点

  • 高层模块调用简单
    一棵树形机构中的所有节点都是Component,局部和整体对调用者来说没有任何区别, 也就是说,高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码。
  • 节点自由增加
    使用了组合模式后,我们可以看看,如果想增加一个树枝节点、树叶节点都很容易,只要找到它的父节点就成,非常容易扩展,符合开闭原则,对以后的维护非常有利。

缺点

直接使用了实现类!这在面向接口编程上是很不恰当的,与依赖倒置原则冲突。

使用场景

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

注意

只要是树形结构,就要考虑使用组合模式,这个一定要记住,只要是要体现局部和整体的关系的时候,而且这种关系还可能比较深,考虑一下组合模式吧。

扩展

真正的组合模式,一般都是通故数据表形成树形结构,它依靠了关系数据库的非对象存储性能。

透明模式

在这里插入图片描述
透明模式是把用来组合使用的方法放到抽象类中。

public class Leaf extends Component {
    @Override
    @Deprecated
    public void add(Component component) {
        throw new UnsupportedOperationException();
    }

    @Override
    @Deprecated
    public void remove(Component component) {
        throw new UnsupportedOperationException();
    }

    @Override
    @Deprecated
    public ArrayList<Component> getChildren() {
        throw new UnsupportedOperationException();
    }
}
public class Client {
    public static void display(Component root){
        for (Component c : root.getChildren()) {
            if (c instanceof Leaf){
                c.doSomething();
            }else {
                display(c);
            }
        }
    }
}

组合模式的遍历

在这里插入图片描述
添加getParent setParent方法。

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;
    }

    public Corp getParent() {
        return parent;
    }

    public void setParent(Corp parent) {
        this.parent = parent;
    }
}
public class Branch extends Corp{
    private ArrayList<Corp> subordinateList = new ArrayList<>();
    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;
    }
}

最佳实践

组合模式在项目中到处都有,比如现在的页面结构一般都是上下结构,上面放系统的 Logo,下边分为两部分:左边是导航菜单,右边是展示区,左边的导航菜单一般都是树形的 结构,比较清晰,有非常多的JavaScript源码实现了类似的树形菜单,大家可以到网上搜索一下。
还有,大家常用的XML结构也是一个树形结构,根节点、元素节点、值元素这些都与我们的组合模式相匹配,之所以本章节不以XML为例子讲解,是因为很少有人还直接读写 XML文件,一般都是用JDOM或者DOM4J了。

标签:Leaf,之禅,组合,Branch,addSubordinate,new,设计模式,public,String
来源: https://blog.csdn.net/weixin_43797872/article/details/113937662

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有