设计模式:组合模式

组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构,Composite使得客户对单个对象和复合对象的使用具有一致性。

组合模式的优缺点:

优点:

  • 可以清楚地定义分层次的复杂类型,表示对象的全部层次或者部分层次 ,它让客户端忽略了层次的差异,方便对整个层次经行控制。
  • 客户端可以一致的使用一个组合模式或对单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端的代码。
  • 在组合模式种增加新的容器构件和叶子构件都很方便,无需对现有类库进行任何修改,符合开闭原则。
  • 为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合可以形成复杂的树形机构,但对树形结构的控制却很简单。

缺点:

在增加新的构件时就比较难咯。而且难以限定,有时候希望在一个容器种能有某些特定的对象,例如在某个文件夹只能有image或者gif等。这个就比较难以实现。

开发中的应用场景:

  • 操作系统的资源管理器
  • GUI中的容器层次图
  • XML文件解析
  • OA系统中,组织结构的处理
  • Junit单元测试框架 : 底层设计就是典型的组合模式,TestCase(叶子)、TestUnite(容器)、Test接口(抽象)

组合模式核心 :

  • component (抽象构件:容器):它可以是接口或者抽象类,为叶子构建和子容器构建对象声明接口,在该角色中可以包含所有子类共有的行为的实现和声明。在抽象构建中定义了访问及管理它的子构件的方法,如增加子构件,删除子构件,获取子构件等。它定义了叶子和容器构件的共同点。
  • leaf(叶子构建):叶子构建可以说就是各种类型的文件!叶子构建没有子构件。它实现了抽象构建中的定义的行为。对于那些访问子容器,删除子容器,增加子容器的就报错。
  • compsite(子容器构建):它在组合模式中表示容器节点对象,容器结点是子节点,可以是子容器,也可以是叶子构建,它提供一个集合来存储子节点。它有容器特征,可以包含子节点。

案例:

使用组合模式,模拟杀毒软件,该软件能够对某个文件夹杀毒,也可以指定对某些文件杀毒。该过程大致可分为4步,代码如下:

步骤1:定义AbstractFile : 抽象文件类,充当抽象构建。

/**
 * AbstractFile: 抽象文件类,充当抽象构建。
 */
public abstract class AbstractFiles {
    public abstract void add(AbstractFiles af);
    public abstract void remove(AbstractFiles af);
    public abstract AbstractFiles get(int  i);
    public abstract void killVirus();
}

步骤2:定义叶子节点:文件类型,在此只写了图片文件。

/**
 * 图片文件,继承自AbstractFiles
 */
public class ImageFile extends AbstractFiles {

    private String name;

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

    @Override
    public void add(AbstractFiles af) {
        System.out.println("不支持该方法");
    }

    @Override
    public void remove(AbstractFiles af) {
        System.out.println("不支持该方法");
    }

    @Override
    public AbstractFiles get(int i) {
        System.out.println("不支持该方法");
        return null;
    }

    @Override
    public void killVirus() {
        System.out.println("开始进行--"+name+"--文件杀毒");
    }
}

 步骤3:文件夹类型

import java.util.ArrayList;

/**
 * 文件夹类型 ,继承自AbstractFiles
 */
public class Folder extends AbstractFiles {

    //文件夹类,所有的都可以用
    private ArrayList<AbstractFiles> list = new ArrayList<AbstractFiles>();
    private String name;
    public Folder(String name) {
        this.name=name;
    }

    @Override
    public void add(AbstractFiles af) {
        list.add(af);
        System.out.println("添加文件成功!");
    }

    @Override
    public void remove(AbstractFiles af) {
        if(list.remove(af)) {
            System.out.println("删除成功");
        }else{
            System.out.println("删除失败");
        }
    }

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

    @Override
    public void killVirus() {
        System.out.println("对文件夹 "+name+" 进行杀毒");
        //递归调用
        for(Object o:list) {
            ((AbstractFiles) o).killVirus();
        }
    }
}

步骤4:测试

/**
 * 测试
 */
public class Client {
    public static void main(String[] args) {
        //创建一个文件类型
        AbstractFiles f1 = new Folder("主文件夹");
        //创建文件
        AbstractFiles file1= new ImageFile("美妙月亮。png");
        AbstractFiles file2= new ImageFile("大海.jpg");
        AbstractFiles file3= new ImageFile("沙漠杨树.gif");
        f1.add(file1);
        f1.add(file2);
        f1.add(file3);
        //file1.killVirus();
        f1.killVirus();
    }
}

测试结果如下图所示:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值