组合模式(结构型)

一、什么是组合模式
组合(Composite)模式是一种对象的行为模式。将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

组合模式的本质:统一叶子对象和组合对象。

组合模式的目的:让客户端不再区分操作的是组合对象还是叶子对象,而是以一个统一的方式来操作。 


二、组合模式的适用性
在开发中, 我们经常可能要递归构建树状的组合结构,比如以下的图书目录树: 

仔细观察上面的类别树,有以下几个明显的特点。

• 有一个根节点,它没有父节点,它可以包含其他的节点。

• 树枝节点,有一类节点可以包含其他的节点,称之为树枝节点,比如“章”、“节”。

• 叶子节点,有一类节点没有子节点,称之为叶子节点,比如“页”

如果碰到类似上面这种,需使用对象树来描述或实现的功能,都可以考虑使用组合模式


三、组合模式的结构
组合模式涉及的角色及其职责如下:

抽象组件(Node)角色:为组合对象和叶子对象声明公共的接口,让客户端可以通过这个接口来访问和管理整个对象树,并可以为这些定义的接口提供缺省的实现。
组合对象(BranchNode)角色:通常会存储子组件(组合对象、叶子对象),定义包含子组件的那些组件的行为,并实现在抽象组件中定义的与子组件有关的操作,例如子组件的添加(addChild)和删除(removeChild)等。
叶子对象(Leaf)角色:定义和实现叶子对象的行为,并且它不再包含其他的子节点对象。

组合模式结构示意源代码如下:

/**
 * 抽象的组件对象,为组合中的对象声明接口,实现接口的缺省行为
 */
abstract class Node {
    abstract public void p();
}

接下来看看组合类的定义,示意代码如下。 

/**
 * 树干节点
 */
class BranchNode extends Node {
    List<Node> nodes = new ArrayList<>();
    String name;

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

    public void add(Node n) {
        nodes.add(n);
    }

    @Override
    public void p() {
        System.out.println(name);
    }
}

再来看看叶子类的定义,示例代码如下。 

/**
 * 树叶节点
 */
class LeafNode extends Node {
    String name;

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

    @Override
    public void p() {
        System.out.println(name);
    }
}

在客户端中使用Component接口来操作组合对象结构,示意代码如下。 

public class Main {
    public static void main(String[] args) {

        BranchNode root = new BranchNode("root");
        BranchNode chapter1 = new BranchNode("chapter1");
        BranchNode chapter2 = new BranchNode("chapter2");
        Node chapter3 = new LeafNode("chapter3");
        Node c11 = new LeafNode("c11");
        Node c12 = new LeafNode("c12");
        BranchNode b21 = new BranchNode("section21");
        Node c211 = new LeafNode("c211");
        Node c212 = new LeafNode("c212");

        root.add(chapter1);
        root.add(chapter2);
        root.add(chapter3);
        chapter1.add(c11);
        chapter1.add(c12);
        chapter2.add(b21);
        b21.add(c211);
        b21.add(c212);

        tree(root, 0);

    }

    static void tree(Node b, int depth) {
        for(int i=0; i<depth; i++) System.out.print("--");
        b.p();

        if(b instanceof BranchNode) {
            for (Node n : ((BranchNode)b).nodes) {
                tree(n, depth + 1);
            }
        }
    }
}

运行程序打印结果如下:  

root
--chapter1
----c11
----c12
--chapter2
----section21
------c211
------c212
--chapter3

从以上的示例可以看出,组合模式的关键就在于抽象组件角色,作为组合对象和叶子对象的父类,这个抽象组件类既可以代表叶子对象,也可以代表组合对象,这样用户在操作的时候,始终是在操作组件对象,不必再去区分是在操作组合对象还是叶子对象,从而使得对叶子对象和组合对象的使用具有了一致性。  


四、组合模式的优缺点
使用组合模式的优点:

  1)  统一了组合对象和叶子对象。
              2)  简化了客户端调用,无须区分操作的是组合对象还是叶子对象。
              3)  更容易扩展,有了Component的约束,新定义的Composite或Leaf子类能够很容易地与已有的结构一起工作。

使用组合模式的缺点: 很难限制组合中的组件类型。 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值