组合模式

前言

组合模式也是结构型模式的一种。node

目录

1、定义

组合模式也叫合成模式,或者称部分-总体模式,主要是用来描述部分与总体的关系。算法

将对象组合成树形结构以表示 “部分-总体” 的层次结构,使得用户对单个对象和组合对象的使用具备一致性。安全

这里有两个关键点:一个是用树形结构来分层,另外一个是经过统一对待来简化操做markdown

2、模式原理分析

模式主要包含三个角色数据结构

  • 抽象组件:定义须要实现的统一操做。ide

  • 组合节点:表明一个能够包含多个节点的复合对象,意味着在它下面还能够有其余组合节点或叶子节点。this

  • 叶子节点:表明一个原子对象,意味着在它下面不会有其余节点了。spa

    //抽象组件 public abstract class Component{ public abstract void operation(); } //叶子节点 public class Leaf extends Component{ @Override public void operation() { //叶子节点的操做放这里 } } //组合节点 public class Node extends Component { private List myChildren; //存放子节点列表 @Override public void operation() { for (Component component: myChildren) { component.operation(); } } public List getAllMyChildren(){ return this.myChildren; } }code

结合上面的组合模式模板代码,能大概了解出组合模式封装了如下变化component

  • 叶子节点和组合节点之间的区别

  • 真实的数据结构,树形?网状?

  • 遍历真实结构的算法,这里不必定非要for循环遍历

  • 结构所使用的一些策略,好比用来汇总的数据

例如建立一个能够生成树形对象功能 (AbstractNode抽象组件中,组合使用的方法都放到了该类,这种称组合模式的透明模式,运行期可能抛异常。还有一种是安全模式,例如上面的模板代码,父类没有子类有的方法,将叶子节点和树枝节点完全分开。)

//1.定义一个抽象组件 AbstractNode,其中定义节点能够作的操做有:判断是否为根节点、获取节点 id、获取节点关联父节点 id、设置 id、设置父 id、增长、删除节点和获取子节点。
public abstract class AbstractNode {
    public abstract boolean isRoot();
    public abstract int getId();
    public abstract int getParentId();
    public abstract void setId(int id);
    public abstract void setParentId(int parentId);
    public abstract void add(AbstractNode abstractNode);
    public abstract void remove(AbstractNode g);
    public abstract AbstractNode getChild(int i);
}
//2.建立组合节点 Node,继承自 AbstractNode 实现定义的 8 种接口方法,其中 List 对象 children 用于存放子节点列表。
public class Node extends AbstractNode {
    private List<AbstractNode> children;
    private int id;
    private int pid;
    public Node() {
        children = new ArrayList<AbstractNode>();
    }
    @Override
    public boolean isRoot() {
        return -1 == pid;
    }
    @Override
    public int getId() {
        return id;
    }

    @Override
    public int getParentId() {
        return pid;
    }

    @Override
    public void setId(int id) {
        this.id = id;
    }

    @Override
    public void setParentId(int parentId) {
        this.pid = parentId;
    }

    public void add(AbstractNode c) {
        c.setParentId(this.pid+children.size());
        c.setId(c.getParentId()+1);
        children.add(c);
    }

    public void remove(AbstractNode c) {
        children.remove(c);
    }

    public AbstractNode getChild(int i) {
        return children.get(i);
    }

}
//3.建立叶子节点 Leaf,一样继承自 AbstractNode,重写 8 种接口方法,不过,由于叶子节点不能新增和删除节点,因此添加和删除方法不支持,而且获取子节点方法也应该为空
public class Leaf extends AbstractNode {

    private int id;
    private int pid;
    @Override
    public boolean isRoot() {
        return false;
    }

    @Override
    public int getId() {
        return this.id;
    }

    @Override
    public int getParentId() {
        return this.pid;
    }

    @Override
    public void setId(int id) {
        this.id = id;
    }

    @Override
    public void setParentId(int parentId) {
        this.pid  = parentId;
    }

    @Override
    public void add(AbstractNode abstractNode) {
        throw new UnsupportedOperationException("这个是叶子节点,没法增长");
    }
    
    @Override
    public void remove(AbstractNode g) {
        throw new UnsupportedOperationException("这个是叶子节点,没法删除");
    }

    @Override
    public AbstractNode getChild(int i) {
        return null;
    }
}
复制代码

场景类

public class Client{
   public static void main(String[] args) {
        AbstractNode rootNode = new Node();
        rootNode.setId(0);
        rootNode.setParentId(-1);
        AbstractNode node1 = new Node();
        node1.add(new Leaf());
        node1.add(new Leaf());
        rootNode.add(new Leaf());
        rootNode.add(new Leaf());
        rootNode.add(node1);

        System.out.println(node1.getId());
   }

}
复制代码

3、使用场景

  • 维护和展现部分-总体关系的场景,如树形菜单、文件和文件夹管理

  • 统一处理一个结构中的多个对象

  • 只要是树形结构,就能够考虑组合模式

4、优势

  • 高层模块调用简单

  • 清晰定义分层结构

  • 快速新增节点,提高组合灵活性

5、缺点

  • 难以限制节点类型

  • 对依赖致使原则破坏

相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息