欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

软件设计模式学习(十二)组合模式

程序员文章站 2024-02-26 12:48:58
...

组合模式

组合模式关注那些存在于叶子构件和容器构件的结构以及它们的组织形式,叶子构件中不能包含成员对象,容器构件中可以包含成员对象,这些成员对象可能是叶子构件对象,也可能是容器构件对象。这些对象可以构成一个树形结构,组合模式是用面向对象的方法处理树形结构。


模式动机

在Windows操作系统的文件目录结构包含文件和文件夹两类对象,其中在文件夹可以包含子文件夹,也可以包含文件。文件夹是容器类,而不同类型的各种文件是成员类,也称为叶子类,一个文件夹也可以作为另一个更大的文件夹的成员。组合模式描述了如何将容器对象和叶子对象进行递归组合,使得用户在使用时无须对它们进行区分,可以做到一致对待容器对象和叶子对象。


模式定义

组合多个对象形成树形结构以表示“整体-部分”的结构层次。


模式结构

软件设计模式学习(十二)组合模式

  1. Component(抽象构件)

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

  2. Leaf(叶子构件)

    叶子构件在组合结构中表示叶子节点对象,叶子节点没有子节点,实现在抽象构件中定义的行为。对于访问及管理子构件的方法,可以通过异常等方式进行处理。

  3. Composite(容器构件)

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

  4. Client(客户类)

    客户类是可以通过抽象构件接口访问和控制组合构件中的对象。


模式分析

组合模式的关键是定义一个抽象构件类,它既可以代表叶子,也可以代表容器,而客户端针对该抽象构件类进行编程,无须知道它到底是叶子还是容器,可以对其进行统一处理。

一般抽象构件类设计为接口或抽象类,将所有子类共有方法声明和实现放在抽象构件类中。对于客户端编程,将针对抽象构件编程,而无须关心其具体子类是容器构件还是叶子构件。

public abstract class Component {

    public abstract void add(Component c);
    public abstract void remove(Component c);
    public abstract Component getChild(int i);
    public abstract void operation();
}

继承抽象构件的是叶子构件则典型代码如下,叶子构件需要实现抽象构建类中声明的所有方法,包括业务方法以及管理和访问子构件的方法,但是叶子构件不包含子构件,因此在在客户端调用叶子构件的子构件管理和访问方法时需提供异常处理或错误提示。

public class Leaf extends Component {

    @Override
    public void add(Component c) {
        //异常处理或错误提示
    }

    @Override
    public void remove(Component c) {
        //异常处理或错误提示
    }

    @Override
    public Component getChild(int i) {
        //异常处理或错误提示
        return null;
    }

    @Override
    public void operation() {
        //实现代码
    }
}

容器构件需要实现抽象构建类中声明的所有方法,包括具体实现业务方法以及管理和访问子构件的方法。由于容器构件充当的是容器角色,包含成员构件,因此它将调用其成员构件的业务方法,使用递归算法,即在容器构件的operation()方法中递归调用其成员构件的operation()方法。

public class Composite extends Component {

    private ArrayList list = new ArrayList();

    @Override
    public void add(Component c) {
        list.add(c);
    }

    @Override
    public void remove(Component c) {
        list.remove(c);
    }

    @Override
    public Component getChild(int i) {
        return (Component) list.get(i);
    }

    @Override
    public void operation() {
        for (Object o : list) {
            ((Component) o).operation();
        }
    }
}

透明组合模式与安全组合模式

组合模式根据抽象构件类的定义形式,又可分为透明组合模式和安全组合模式

  1. 透明组合模式

    透明组合模式中,抽象构件Component中声明所有用于管理成员对象的方法,这样做的好处是确保所有构件类都有相同的接口。在客户端看来,叶子对象与容器对象所提供的方法是一致的,客户端可以相同地对待所有的对象。缺点是不够安全,因为叶子对象和容器对象在本质上是有区别的。
    软件设计模式学习(十二)组合模式

  2. 安全组合模式

    安全组合模式中抽象构件Component中没有声明任何用于管理成员对象的方法,而是在Composite类中声明这些用于管理成员对象的方法。对于叶子对象,客户端不可能调用到管理成员对象的方法。缺点是不够透明,客户端不能完全针对抽象编程。 软件设计模式学习(十二)组合模式

相关标签: 软件设计模式