TypechoJoeTheme

IT技术分享

统计

组合模式(Composite)——23种设计模式之结构型模式

2016-04-19
/
0 评论
/
485 阅读
/
正在检测是否收录...
04/19

在面向对象的系统中,我们常会遇到一类具有 “容器”特征的对象-->它们在充当对象的同时, 又是其他对象的容器。如果我们要对这样的对象容器进行处理,将面 临比较复杂的递归过程。

客户代码过多地依赖于对象容器复杂的内部实现结构, 对象容器内部实现结构(而非抽象接口)的变化将引起 客户代码的频繁变化,带来了代码的维护性、扩展性 差等问题。

如何将“客户代码与复杂的对象容器结构”解耦?让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂的对象容器?

如果一些部件对象经过组合构成的复合部件对象仍然具有 单个部件对象的接口,这样的复合部件对象被称为 “容器(container)”。复合部件与单个部件具有同样的接口,所有接口包含两部分:单个部件的功能、管理子部件的功能,这样的结构具有递归组合特点,在这种场景下,我们引入“组合模式”来解决“客户端代码与复杂的对象容器结构”解耦的问题。

一、类图表示

组合模式涉及到Component (抽象构件类),Leaf (叶子),Composite (容器对象),Client(客户端)等四个角色

  • ①、Leaf (叶子):在组合中表示叶节点对象,没有子节点,在组合中定义图元对象的行为
  • ②、Composite (容器对象):定义有子部件的那些部件的行为,存储子部件,在Component接口中实现与子部件有关的操作
  • ③、Client(客户端):通过Component接口操纵组合部件的对象
  • ④、Component (抽象构件类):为组合中的对象声明接口,在适当的情况下实现所有类共有接口的缺省行为,声明一个接口用于访问和管理Component的子组件,(可选)在递归结构中定义一个接口,用于访问一个父部件,并在 合适的情况下实现它。

1、安全组合模式

只有容器构件角色才配备管理聚集的方法,而叶子构 件没有这些方法

java-composite-model-1

2、透明式组合模式

容器构件和叶子构件角色都配备管理聚集的方法。

java-composite-model-2

二、代码示例

public interface Component {
    public void operation();

    public boolean add(Component o);

    public boolean remove(Component o);

    public List getChildren();
}
public class Composite implements Component {
    private String name;
    private List children = new ArrayList();

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

    public void operation(){
        System.out.println(name);
    }

    public boolean add(Component o){
        if(!children.contains(o)){
            children.add(o);
        }
        return true;
    }

    public boolean remove(Component o){
        children.remove(o);
        return true;
    }

    public List getChildren(){
        return children;
    }
}
public class Leaf implements Component {
    private String name;

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

    public void operation(){
        System.out.println(name);
    }

    public boolean add(Component o){
        return false;
    }

    public boolean remove(Component o){
        return false;
    }

    public List getChildren(){
        return null;
    }
}
public class Client {
    private static void doCircle(Component o){
        List list = o.getChildren();
        if(list!=null && list.size()>0){
            for(int i=0;i<list.size();i++){
                Component sub = (Component)list.get(i);
                sub.operation();

                //递归执行
                doCircle(sub);
            }
        }
    }

    public static void main(String[] args) {
        Component root = new Composite("树干");

        Component comp1 = new Composite("树枝一");
        Component comp2 = new Composite("树枝二");
        root.add(comp1);
        root.add(comp2);

        Component leaf1 = new Leaf("叶一");
        Component leaf2 = new Leaf("叶二");
        comp1.add(leaf1);
        comp1.add(leaf2);

        doCircle(root);

    }
}

三、优缺点分析

1、优点

  • ①、定义了包含leaf对象和composite对象的类层次接口—— 递归结构
  • ②、简化客户代码,因为客户端不需要知道构件是叶子还是容器对象,客户一致地处理复合对象和单个对象
  • ③、使得更容易增加新类型的组件,易于增加新类型的组件
  • ④、使设计变得更加一般化,无法限制类型的组合,可以在运行时刻通过类型检查加以弥补

2、缺点

  • ①、使用组合模式后,控制容器对象的类型就不太容易。
  • ②、用继承的方法增加新的行为很困难。

四、与其它模式的关系

1、与装饰者模式关系

  • ①、Decorator经常和Composite一起使用,通常有一个 公共的父类

2、与享元模式的关系

  • ①、Flyweight可以共享组件但是不再能引用他们的父类对象

3、与迭代器模式的关系

  • ①、Iterator:可用来遍历Composite

4、与访问者模式的关系

  • ①、Visitor:将本来应该分布在Composite和Leaf类中的操作和行为局部化

五、总结

组合模式是很多复杂模式的一部分

  • ①、组合模式的关键是定义了一个抽象构件类, 它既可以代表叶子,又可以代表容器,而客 户端针对该抽象构件类进行编程,无须知道 它到底表示的是叶子还是容器,可以对其进 行统一处理。
  • ②、同时容器对象与抽象构件类之间还建立一个 聚合关联关系,在容器对象中既可以包含叶 子,也可以包含容器,以此实现递归组合, 形成一个树形结构。
朗读
赞 · 0
版权属于:

IT技术分享

本文链接:

https://idunso.com/archives/1838/(转载时请注明本文出处及文章链接)