13、组合模式

文章目录

  • 组合模式

    • 优点

    • 缺点

    • 适用环境

    • 透明组合模式

    • 安全组合模式

    • 概述

    • 结构

    • 结构实现

    • 练习

    • 源代码

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

    • 组合模式优/缺点与适用环境

概述

组合模式:组合多个对象形成树形结构以表示具有部分-整体关系的层次结构。组合模式让客户端可以统一对待单个对象和组合对象。

组合模式又称为“部分-整体”模式,属于对象结构型模式,它将对象组织到树形结构中,可以用来描述整体与部分的关系。

组合模式使用面向对象的方式来处理树形结构,它为叶子构件和容器构件提供了一个公共的抽象构件类,客户端可以针对抽象构件进行处理,而无须关心所操作的是叶子构件还是容器构件。

结构

组合模式包含以下3个角色:

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

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

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

结构实现

抽象构件角色:一般设计为接口或抽象类,将所有子类共有方法的声明和实现放在抽象构件类中。

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(); //业务方法
}

继承抽象构件的是叶子构件:叶子构件不能再包含子构件,因此在叶子构件中实现子构件管理和访问方法时需要提供异常处理或错误提示。

class Leaf extends Component {public void add(Component c) {
        //异常处理或错误提示
    }

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

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

    public void operation() {//叶子构件具体业务方法的实现
    }
}

如果继承抽象构件的是容器构件:在容器构件中实现了在抽象构件中声明的所有方法,既包括业务方法,也包括用于访问和管理成员子构件的方法。在组合模式结构中,由于容器构件中仍然可以包含容器构件,因此在对容器构件进行处理时需要使用递归算法。

class Composite extends Component {private ArrayList<Component> list = new ArrayList<Component>();

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

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

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

    public void operation() {//容器构件具体业务方法的实现
        //递归调用成员构件的业务方法
        for(Object obj:list) {((Component)obj).operation();
        }
    }
}

练习

某软件公司欲开发一个杀毒(Antivirus)软件,该软件既可以对某个文件夹(Folder)杀毒,也可以对某个指定的文件(File)进行杀毒。该杀毒软件还可以根据各类文件的特点,为不同类型的文件提供不同的杀毒方式,例如图像文件(ImageFile)和文本文件(TextFile)的杀毒方式就有所差异。现使用组合模式来设计该杀毒软件的整体框架。

源代码

AbstractFile.java:

package composite;

public abstract class AbstractFile {public abstract void add(AbstractFile file);
    public abstract void remove(AbstractFile file);
    public abstract AbstractFile getChild(int i);
    public abstract void killVirus();
}

ImageFile.java:

package composite;

public class ImageFile extends AbstractFile {private String name;

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

    public void add(AbstractFile file){System.out.println("对不起,不支持该方法!");
    }

    public void remove(AbstractFile file) {System.out.println("对不起,不支持该方法!");
    }

    public AbstractFile getChild(int i) {System.out.println("对不起,不支持该方法!");
        return null;
    }

    public void killVirus() {//模拟杀毒
        System.out.println("----对图像文件‘" name "’进行杀毒");
    }
}

TextFile.java:

package composite;

public class TextFile extends AbstractFile {private String name;

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

    public void add(AbstractFile file) {System.out.println("对不起,不支持该方法!");
    }

    public void remove(AbstractFile file) {System.out.println("对不起,不支持该方法!");
    }

    public AbstractFile getChild(int i) {System.out.println("对不起,不支持该方法!");
        return null;
    }

    public void killVirus() {//模拟杀毒
        System.out.println("----对文本文件‘" name "’进行杀毒");
    }
}

VideoFile.java:

package composite;

public class VideoFile extends AbstractFile {private String name;

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

    public void add(AbstractFile file) {System.out.println("对不起,不支持该方法!");
    }

    public void remove(AbstractFile file) {System.out.println("对不起,不支持该方法!");
    }

    public AbstractFile getChild(int i) {System.out.println("对不起,不支持该方法!");
        return null;
    }

    public void killVirus() {//模拟杀毒
        System.out.println("----对视频文件‘" name "’进行杀毒");
    }
}

Folder.java:

package composite;

import java.util.ArrayList;

public class Folder extends AbstractFile {//定义集合fileList,用于存储AbstractFile类型的成员
    private ArrayList<AbstractFile> fileList = new ArrayList<AbstractFile>();
    private String name;

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

    public void add(AbstractFile file) {fileList.add(file);
    }

    public void remove(AbstractFile file) {fileList.remove(file);
    }

    public AbstractFile getChild(int i) {return (AbstractFile)fileList.get(i);
    }

    public void killVirus() {System.out.println("****对文件夹‘" name "’进行杀毒");//模拟杀毒
        //递归调用成员构件的killVirus()方法
        for(Object obj : fileList){((AbstractFile)obj).killVirus();
        }
    }
}

Client.java:

package composite;

public class Client {public static void main(String[] args) {//针对抽象构件编程
        AbstractFile file1,file2,file3,file4,file5,folder1,folder2,folder3,folder4;

        folder1 = new Folder("Sunny的资料");
        folder2 = new Folder("图像文件");
        folder3 = new Folder("文本文件");
        folder4 = new Folder("视频文件");

        file1 = new ImageFile("小龙女.jpg");
        file2 = new ImageFile("张无忌.gif");
        file3 = new TextFile("九阳真经.txt");
        file4 = new TextFile("葵花宝典.doc");
        file5 = new VideoFile("笑傲江湖.rmvb");

        folder2.add(file1);
        folder2.add(file2);
        folder3.add(file3);
        folder3.add(file4);
        folder4.add(file5);
        folder1.add(folder2);
        folder1.add(folder3);
        folder1.add(folder4);

        //从“Sunny的资料”结点开始进行杀毒操作
        folder1.killVirus();
    }
}

运行结果:

****对文件夹‘Sunny的资料’进行杀毒
****对文件夹‘图像文件’进行杀毒
----对图像文件‘小龙女.jpg’进行杀毒
----对图像文件‘张无忌.gif’进行杀毒
****对文件夹‘文本文件’进行杀毒
----对文本文件‘九阳真经.txt’进行杀毒
----对文本文件‘葵花宝典.doc’进行杀毒
****对文件夹‘视频文件’进行杀毒
----对视频文件‘笑傲江湖.rmvb’进行杀毒

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

透明组合模式

透明组合模式中,抽象构件Component中声明了所有用于管理成员对象的方法,包括add()、remove()以及getChild()等方法。

这样做的好处是确保所有的构件类都有相同的接口。在客户端看来,叶子对象与容器对象所提供的方法是一致的,客户端可以相同地对待所有的对象。

透明组合模式的缺点是不够安全,因为叶子对象和容器对象在本质上是有区别的。叶子对象不可能有下一个层次的对象,即不可能包含成员对象,因此为其提供add()、remove()以及getChild()等方法是没有意义的。

安全组合模式

安全组合模式中,在抽象构件Component中没有声明任何用于管理成员对象的方法,而是在Composite类中声明并实现这些方法。

这种做法是安全的,因为根本不向叶子对象提供这些管理成员对象的方法,对于叶子对象,客户端不可能调用到这些方法。

安全组合模式的缺点是不够透明,因为叶子构件和容器构件具有不同的方法,且容器构件中那些用于管理成员对象的方法没有在抽象构件类中定义,因此客户端不能完全针对抽象编程,必须有区别地对待叶子构件和容器构件。

在实际应用中,安全组合模式的使用频率更高。

组合模式优/缺点与适用环境

优点

  1. 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个层次结构进行控制。

  2. 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码。

  3. 在组合模式中增加新的容器构件和叶子构件都很方便,无须对现有类库进行任何修改,符合“开闭原则”。

  4. 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。

缺点

在增加新构件时很难对容器中的构件类型进行限制。有时候我们希望一个容器中只能有某些特定类型的对象,例如在某个文件夹中只能包含文本文件,使用组合模式时,不能依赖类型系统来施加这些约束,因为它们都来自于相同的抽象层,在这种情况下,必须通过在运行时进行类型检查来实现,这个实现过程较为复杂。

适用环境

  1. 在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们。

  2. 在一个使用面向对象语言开发的系统中需要处理一个树形结构。

  3. 在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型。


本篇文章参考书籍有:
《Java设计模式》 刘伟——清华大学出版社,2018


作者:阿涛

来源:https://www.icode9.com/content-4-791451.html

(0)

相关推荐

  • DercoratorPattern装饰者模式

    装饰者模式 1,定义 动态的给一个对象添加一些额外的职责. 装饰者模式通常有4个角色,就增加功能来说,装饰者模式比生成子类更加的灵活. Component:抽象构件.通常是一个接口或者抽象类,定义最核 ...

  • C#设计模式-组合模式(Composite Pattern)

    概念 组合是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们. 组合模式(Composite Pattern)是将对象组合成树形结构以表示'部分-整体'的层次 ...

  • 设计模式-结构型-装饰者模式

    装饰者模式(wrapper): 允许向一个现有的对象添加新的功能,同时又不改变其结构.装饰器模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能.使用对象的关联关系代替继承关系,更加 ...

  • 详解JAVA面向对象的设计模式 (七)、装饰模式

    装饰模式 Decorator 装饰模式比较简单,我就不单独写实现例子了.参考设计图去实现不是什么问题.建议可以写一写找找感觉. 在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修.相 ...

  • Composite组合模式

    >>返回<C#常用设计模式> 1. 简介 2. 示例 3. 适用环境 1. 简介 定义 组合多个对象形成树形结构以表示具有部分-整体关系的层次结构. 组合模式让调用程序可以统一 ...

  • 设计模式(十)——组合模式(HashMap源码解析)

    设计模式(十)——组合模式(HashMap源码解析)

  • java学习——48.容器、窗口、面板和框架类

    java学习——48.容器、窗口、面板和框架类

  • 结构型设计模式 - 组合模式详解

    基本介绍 1.组合模式(Composite Pattern)又叫部分整体模式,他创建了对象组的树形结构,将对象组合成树状结构以表示「整体 - 部分」的层次关系. 2.组合模式使得用户对单个对象和组合对 ...

  • 【3/25】使用组合模式(Composite Pattern)实现布局容器

    这是<小游戏从0到1设计模式重构>系列内容第3篇,所有源码及资料在"程序员LIYI"公号回复"小游戏从0到1"获取. 组合模式(Composite) ...

  • 打板模型图解:涨停双响炮的三种K线组合模式

    我们知道股市中大幅连续大阳线拉升的股票很少见,更多的还是大阳线后会接连几天出现调整,实战中我们往往不敢在其调整时贸然下手,股市中谨慎永远没有错,这种态度无可厚非,谁也不知道这到底是调整还是庄家在出货, ...

  • PHP设计模式之组合模式

    PHP设计模式之组合模式 互联网公司流行扁平化管理,也就是管理层级尽量少于或者不超过三层,作为一个底层的码农,你的CEO和你的职级也就相差3层以内.但是很多传统企业,则会有非常深的层级关系,从数据结构 ...

  • [PHP小课堂]PHP设计模式之组合模式

    [PHP小课堂]PHP设计模式之组合模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • 【随队记者专栏】“巴特勒+伊戈达拉”:热火在新赛季再次冲冠的组合模式

    上个周末是关于自由球员的.下周将是训练营的开启之时.这就是休赛期的旋风. 不可能有多少喘息的时间,只是第二次风力加速. 那么,迈阿密热火如何才能从30支球队中脱颖而出呢? 三个想法: --它(趋势)正 ...

  • 邮政新一代寄递平台“月份组合”模式的投递排班表查询方法

    近期,遇有一基层投递部反馈:一名投递员病假,需修订排班表,但新一代寄递平台查不到已维护完毕的排班表?咨询如何解决. 经小编了解,上述问题解决实际非常简单.该投递班组遇到问题为"月份组合&qu ...

  • 八字五行十神的动态组合模式

    命理学所依据的原理是中国的易学.作为代表世界文明发展的群经之首--<易经>,最核心的原则是天地人之间的平衡.但其依存关系处于变化中,在变动中不断形成新的平衡. 这些由五行十神之间的生克而形 ...