组合模式(Composite Pattern)

组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

组合模式让你可以优化处理递归或分级数据结构。有许多关于分级数据结构的例子,使得组合模式非常有用武之地。关于分级数据结构的一个普遍性的例子是你每次使用电脑时所遇到的:文件系统。文件系统由目录和文件组成。每个目录都可以装内容。目录的内容可以是文件,也可以是目录。按照这种方式,计算机的文件系统就是以递归结构来组织的。如果你想要描述这样的数据结构,那么你可以使用组合模式Composite。


效果:

1.定义了包含基本对象和组合对象的类层次结构:

基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断的递归下去。客户代码中,任何用到   基本对象的地方都可以使用组合对象。
2.简化客户代码:

客户可以一致地使用组合结构和单个对象。通常用户不知道 (也不关心)处理的是一个叶节点还是一个组合组件。这就简化了客户代码 , 因为在定义组合的那些类中不需要写一些充斥着选择语句的函数。
3.使得更容易增加新类型的组件:

新定义的Composite或Leaf子类自动地与已有的结构和客户代码一起工作,客户程序不需因新的Component类而改变。
4.使你的设计变得更加一般化:

容易增加新组件也会产生一些问题,那就是很难限制组合中的组件。有时你希望一个组合只能有某些特定的组件。使用Composite时,你不能依赖类型系统施加这些约束,而必须在运行时刻进行检查。


涉及角色:
1.Component 是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。
2.Leaf 在组合中表示叶子结点对象,叶子结点没有子结点。
3.Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。

类图:



ER图:



代码示例:

假设现在需要设计一套角色系统,包括组长和组员,组员又可以是其他组的组长。组长可以新增、删除组员,同时还必须知道下面所有的组员名字。


public abstract class Role {

    private String name;

    public Role(){}

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public abstract void add(Role role);
    public abstract void remove(Role role);
    public abstract void display();
    public abstract Role getChild(int i);
}


public class TeamLeader extends Role {

    private List<Role> list;

    public TeamLeader(){
        list = new ArrayList<Role>();
    }

    public TeamLeader(String name){
        super(name);
        list = new ArrayList<Role>();
    }

    @Override
    public void add(Role role) {
        list.add(role);
    }

    @Override
    public void remove(Role role) {
        list.remove(role);
    }

    @Override
    public void display() {
        System.out.println(this.getName());
        for (Role p : list){
            p.display();
        }

    }

    @Override
    public Role getChild(int i) {
        System.out.println(this.getName()+"的第"+(i+1)+"个组员是"+list.get(i).getName());
        return list.get(i);
    }
}
public class Member extends Role {

    public Member(){};

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

    @Override
    public void add(Role role) {
        System.out.println(this.getName()+"不能够添加组员");
    }

    @Override
    public void remove(Role role) {
        System.out.println(this.getName()+"不能够删除组员");
    }

    @Override
    public void display() {
        System.out.println(this.getName());
    }

    @Override
    public Role getChild(int i) {
        System.out.println(this.getName()+"没有组员");
        return null;
    }
}
测试方法:

public static void main(String[] args) {
    Role p1 = new TeamLeader("张组长");
    Role p2 = new TeamLeader("陈组长");
    Role p3 = new Member("组员a");
    Role p4 = new Member("组员b");
    Role p5 = new Member("组员c");
    Role p6 = new Member("组员d");
    Role p7 = new Member("组员e");
    p1.add(p2);
    p1.add(p3);
    p1.add(p4);
    p1.add(p5);
    p2.add(p6);
    p2.add(p7);
    p1.display();
    p2.getChild(1);
    p5.getChild(1);
}

执行结果:

张组长
陈组长
组员d
组员e
组员a
组员b
组员c
陈组长的第2个组员是组员e
组员c没有组员


结果分析:

这个案例中,组长-组员就组成了一个树形结构。p1.display()方法将组长p1下的各级组员的名字都显示了出来,对于组长或者组员来说,都实现了display这个方法,显示名称。这样对于客户端来说,处理组长和处理组员就是一样的操作了。这也就是组合模式希望的结果。在组长和组员中实现角色接口中的抽象方法,各自完成自身的逻辑。

组合模式解耦了客户程序与复杂元素内部结构,从而使客户程序可以像处理简单元素一样来处理复杂元素。
如果你想要创建层次结构,并可以在其中以相同的方式对待所有元素,那么组合模式就是最理想的选择。例如文件系统中,文件与目录组成了一个树形结构;网站导航中各级目录结果也是一个树形结构。类似这样的树形结构,都可以考虑使用组合模式。











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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值