设计模式之结构型模式(三)组合模式

110 阅读3分钟

1.适配器模式 2.桥接模式 3.组合模式 4.代理模式 5.装饰模式 6.外观模式 7.享元模式

由于学习难度较大 并且相对用途较少 本章不会讲解享元模式

接下来针对以上6种设计模式进行单独讲解

3 组合模式

3.1 定义

组合多个对象形成树形结构以表示具有“部分—整体”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,又可以称为“部分—整体”模式

组合模式主要处理软件开发中的树形结构,如目录结构,菜单,公司组织架构等。这些结构具有的共同特点都是可以有子菜单,子菜单下还可以包含子菜单或者最终菜单

组合模式使得用户可以一致性的处理该树形结构的整体或者部分,也可以一致性的处理树形结构的叶子节点和容器节点(例如文件夹可以包含子文件夹和文件,其中文件夹就是该树形结构的容器节点,文件为该树形结构的叶子节点) 如下图所示

3.2 UML图

image.png 从上面UML图中可以看出

Component为抽象节点,为叶子节点和容器节点对象声明接口,在该角色中可以包含所有子类共有行为的声明和实现。在抽象构件中定义了访问及管理它的子构件的方法,例如增加子节点、删除子节点、获取子节点等

Leaf为叶子节点,实现了在Component中定义的行为。叶子节点没有子节点,所以对add,remove,getChild方法不做实现或者直接抛出异常

Composite为容器节点,容器节点包含子节点,其子节点可以是叶子节点,也可以是容器节点。提供一个集合用于存储子节点,实现了在抽象构件中定义的行为,包括那些访问及管理子构件的方法,在其业务方法中可以递归调用其子节点的业务方法

client直接调用Component的operation方法,通过该方法屏蔽具体的容器节点和叶子节点的具体实现

3.3 代码实现

// 抽象节点  
public abstract class Component {  
    // 添加子节点  
    public abstract void add(Component child);  
    // 删除子节点  
    public abstract void remove(Component child);  
    // 获取子节点  
    public abstract Component getChild(int index);  
    // 具体操作方法,由子类实现  
    public abstract void operation();  
}  
  
// 叶子节点  
public class Leaf extends Component {  
    private String name;  
  
    public Leaf(String name) {  
        this.name = name;  
    }  
  
    @Override  
    public void add(Component child) {  
        throw new UnsupportedOperationException("Leaf node does not support add operation");  
    }  
  
    @Override  
    public void remove(Component child) {  
        throw new UnsupportedOperationException("Leaf node does not support remove operation");  
    }  
  
    @Override  
    public Component getChild(int index) {  
        throw new UnsupportedOperationException("Leaf node does not have children");  
    }  
  
    @Override  
    public void operation() {  
        System.out.println("Leaf " + name + " operation");  
    }  
}  
  
  
// 容器节点  
public class Composite extends Component {  
    private List<Component> children = new ArrayList<>();  
  
    @Override  
    public void add(Component child) {  
        children.add(child);  
    }  
  
    @Override  
    public void remove(Component child) {  
        children.remove(child);  
    }  
  
    @Override  
    public Component getChild(int index) {  
        return children.get(index);  
    }  
  
    @Override  
    public void operation() {  
        System.out.println("Composite operation");  
        for (Component child : children) {  
            child.operation();  
        }  
    }  
}
//客户端
public class client{
    public static void main(String args[]){
       Component composite = new Composite();
       Component leaf1 = new Leaf("1");  
       composite.add(leaf1);  
        // 执行操作方法,从根节点开始遍历并执行所有叶节点的操作方法  
        composite.operation()
    }
}

3.4 拓展

透明组合模式和安全组合模式 所谓透明是指叶子节点和容器节点都实现抽象组件Component的所有方法,例如上例中都叶子节点和容器节点都实现了add,remove,getChild方法,但是叶子节点其实不具有这些特性,这样做可以保证在编译时不报错,但是具体在运行时如果客户端不知道这些区别会导致运行时异常。 安全模式将这些容器节点具有的特有方法都下沉到容器节点进行实现(上述例子中的Composite节点),抽象节点(Component)只暴露叶子节点和容器节点共有的方法。