设计模式学习笔记05-Composite模式

本文主要是看了《设计模式》做的笔记和思考,在此分享仅代表个人观点,如有不对的地方欢迎批评和指正。

1. 基础

Composite(组合)模式主要是解决嵌套结构中对象之间的关系,比如文件和文件夹,这两者在大多数情况下还具有很多共同点。Composite模式的UML图如下(照着我书上画的)。


Composite的UML图

稍微解释一下:

  • Component 提供一个统一Leaf和Composite的抽象,里面有通用的接口。
  • Leaf 叶子节点,相当于文件系统中的文件,没有子节点。
  • Composite 类似容器的概念,相当于文件系统中的文件夹,可能有子节点。
  • Client 调用者

这里重点是Component的统一抽象,正是因为这个才能统一Leaf和Composite的接口,因此Component中要尽可能地定义通用接口,以满足Leaf和Composite的需要。

1.1 好处

  1. 这个模式定义了基本对象和组合对象,组合对象也可以跟其他组合对象组合成更复杂的对象;
  2. 能够方便地设计基本对象和组合对象的共同属性和行为;
  3. Leaf和Composite的子类可以方便地接入原有的体系;
  4. 可以通过递归方便地遍历整个结构

1.2 部分实现

在Component中,方法都应该设置为省缺实现,便于照顾叶子节点,比如其中的add操作。这样Leaf就可以不再重写add方法,缩减代码量。

class Component{
    void add(Component cpn){
        return;
    }
}

为了保存子节点,Composite需要用到一些存储结构,比如列表、树等等,主要是看性能。

class Composite extends Component{
    private ArrayList list;
    @Override
    void add(Component cpn){
        list.add(cpn);
    }
    // remove类似

    @Override
    Component getChild(int pos){
        return list.get(pos);
    }
}

2. 其他可选设计

2.1 显式的父节点引用

为了方便查找和遍历,可以显式地引入父节点的引用,比如这样:

class Component{
    private Component father;

    protected void setFather(Component father){
        this.father = father;
    }
    public Component getFather(){
        if(father == null){
            throw new Exception("没有父节点");
        }
    }
}

class Composite extends Component{
    private ArrayList list;
    @Override
    void add(Component cpn){
        cpn.setFather(this);
        list.add(cpn);
    }
}

2.2 子节点排序

只有排序后才能更快地进行查询,你可以根据自己使用的语言编写相应代码,比如在Java中实现Comparable接口即可在加入List时自动排序。

2.3 缓存子节点

为了应对频繁的检索,有时可以设置一个缓存,避免了多次遍历,提高效率,比如当你存储子节点的结构是树或者链表。

class Composite extends Component{
    private HashMap map;

    private static int idHolder;
    private static Component cpnHolder;

    @Override
    Component getChild(int id){
        if(id != idHolder && cpnHolder == null){
            idHolder = id;
            cpnHolder = map.get(id);
        }
        return cpnHolder;
    }
}

不过需要注意的是,当子节点发生变化时也需要更新缓存,保证其正确性。

3. 总结

该模式很好地处理了嵌套结构中,组合对象身份多样的情况,并且提供了统一的抽象来简化代码和使用,实际的例子有Android中View与ViewGroup,有相关编程经验的读者应该深有体会。

你可能感兴趣的:(设计模式学习笔记05-Composite模式)