23种常用设计模式之组合模式

说明

组合模式(Composite Pattern),又叫部分整体模式,是一种结构型模式。它将对象组合成树形结构以表示"部分-整体"的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性

应用场景

部分、整体场景,如树形菜单,文件、文件夹的管理

模式特征

角色 说明 举栗
抽象根节点(Component) 定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性 TransparentComponent、SecurityComponent
树枝节点(Composite) 定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构 TransparentComposite、SecurityComposite
叶子节点(Leaf) 叶子节点对象,其下再无分支,是系统层次遍历的最小单位 TransparentLeaf、SecurityLeaf

实现方式

  • 透明模式:透明模式是把组合使用的方法放到抽象类中,不管叶子对象还是树枝对象都有相同的结构,这样做的好处就是叶子节点和树枝节点对于外界没有区别,它们具备完全一致的行为接口。但因为Leaf类本身不具备add()、remove()方法的功能,所以实现它是没有意义的
  • 安全模式:安全模式是把树枝节点和树叶节点彻底分开,树枝节点单独拥有用来组合的方法,这种方法比较安全。但由于不够透明,所以树叶节点和树枝节点将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。

UML

透明模式

透明模式类图

安全模式

安全模式类图

代码实现

透明模式
  • 抽象根节点:TransparentComponent
public abstract class TransparentComponent {
    protected String name;

    public TransparentComponent(String name){
        this.name = name;
    }

    //添加一个子节点
    public abstract void add(TransparentComponent component);

    //移除一个子节点
    public abstract void remove(TransparentComponent component);

    //展示节点信息
    public abstract void display(int depth);
}
  • 树枝节点:TransparentComposite
public class TransparentComposite extends TransparentComponent {

    //子节点容器
    private List<TransparentComponent> components = new ArrayList<>();

    public TransparentComposite(String name) {
        super(name);
    }

    @Override
    public void add(TransparentComponent component) {
        this.components.add(component);
    }

    @Override
    public void remove(TransparentComponent component) {
        this.components.remove(component);
    }

    @Override
    public void display(int depth) {
        //输出树形结构
        for (int i = 0; i < depth; i++) {
            System.out.print('-');
        }
        System.out.println(name);

        //下级遍历
        for (TransparentComponent component : components) {
            component.display(depth + 1);
        }
    }
}
  • 叶子节点:TransparentLeaf
public class TransparentLeaf extends TransparentComponent {

    public TransparentLeaf(String name) {
        super(name);
    }

    //叶子节点不允许添加component
    @Override
    public void add(TransparentComponent component) {
        throw new UnsupportedOperationException("Leaf cannot add component");
    }

    //叶子节点不允许删除component
    @Override
    public void remove(TransparentComponent component) {
        throw new UnsupportedOperationException("Leaf have not component to remove");
    }

    @Override
    public void display(int depth) {
        //输出树形结构的叶子节点
        for (int i = 0; i < depth; i++) {
            System.out.print('-');
        }
        System.out.println(name);
    }
}
  • 客户端测试类
public class Client {
    public static void main(String[] args) {
        //创建根节点及其叶子节点
        TransparentComposite root = new TransparentComposite("root");
        root.add(new TransparentLeaf("Leaf 1_1"));
        root.add(new TransparentLeaf("Leaf 1_2"));

        //创建二层树枝节点及其叶子节点,并将其添加到根节点
        TransparentComposite branch = new TransparentComposite("Branch 1_1");
        branch.add(new TransparentLeaf("Leaf 2_1"));
        branch.add(new TransparentLeaf("Leaf 2_2"));
        root.add(branch);

        //创建三层树枝节点及其叶子节点,并将其添加到branch
        TransparentComposite branch1 = new TransparentComposite("Branch 2_1");
        branch1.add(new TransparentLeaf("Leaf 3_1"));
        branch1.add(new TransparentLeaf("Leaf 3_2"));
        branch.add(branch1);

        root.display(1);
    }
}
安全模式
  • 抽象根节点:SecurityComponent
public abstract class SecurityComponent {
    protected String name;

    public SecurityComponent(String name){
        this.name = name;
    }

    //展示节点信息
    public abstract void display(int depth);
}
  • 树枝节点:SecurityComposite
public class SecurityComposite extends SecurityComponent {

    //子节点容器
    private List<SecurityComponent> components = new ArrayList<>();

    public SecurityComposite(String name) {
        super(name);
    }

    public void add(SecurityComponent component) {
        this.components.add(component);
    }

    public void remove(SecurityComponent component) {
        this.components.remove(component);
    }

    @Override
    public void display(int depth) {
        //输出树形结构
        for (int i = 0; i < depth; i++) {
            System.out.print('-');
        }
        System.out.println(name);

        //下级遍历
        for (SecurityComponent component : components) {
            component.display(depth + 1);
        }
    }
}
  • 叶子节点:SecurityLeaf
public class SecurityLeaf extends SecurityComponent {

    public SecurityLeaf(String name) {
        super(name);
    }

    @Override
    public void display(int depth) {
        //输出树形结构的叶子节点
        for (int i = 0; i < depth; i++) {
            System.out.print('-');
        }
        System.out.println(name);
    }
}
  • 客户端测试类
public class Client {
    public static void main(String[] args) {
        //创建根节点及其叶子节点
        SecurityComposite root = new SecurityComposite("root");
        root.add(new SecurityLeaf("Leaf 1_1"));
        root.add(new SecurityLeaf("Leaf 1_2"));

        //创建二层树枝节点及其叶子节点,并将其添加到根节点
        SecurityComposite branch = new SecurityComposite("Branch 1_1");
        branch.add(new SecurityLeaf("Leaf 2_1"));
        branch.add(new SecurityLeaf("Leaf 2_2"));
        root.add(branch);

        //创建三层树枝节点及其叶子节点,并将其添加到branch
        SecurityComposite branch1 = new SecurityComposite("Branch 2_1");
        branch1.add(new SecurityLeaf("Leaf 3_1"));
        branch1.add(new SecurityLeaf("Leaf 3_2"));
        branch.add(branch1);

        root.display(1);
    }
}
结果
-root
--Leaf 1_1
--Leaf 1_2
--Branch 1_1
---Leaf 2_1
---Leaf 2_2
---Branch 2_1
----Leaf 3_1
----Leaf 3_2

优缺点

优点

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

缺点

使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒转原则

原创文章 67 获赞 31 访问量 5万+

猜你喜欢

转载自blog.csdn.net/u012534326/article/details/102546641