美文网首页
组合模式

组合模式

作者: 炫迈哥 | 来源:发表于2017-03-14 17:28 被阅读0次

类图:


精髓

  • 树形结构,可以表现出对象的层次结构,与部分-整体的关系
  • (精髓中的精髓)节点实现同一个公共接口,使得用户对单个对象和组合对象的使用具有一致性(如果组合对象和单个对象行为上没什么区别(如文件夹和文件,行为就基本不一样,如果只是一个纯粹的树状结构的任务执行计划,每个节点都是单个对象而已,只是执行顺序不同,就没必要抽象公共接口了,判断叶子节点就是判断children字段是否为空),抽象接口这一层也可以免去)....也正是因为所有节点都属于同一类,才能如此方便的构造一个树结构出来。

tips:leaf与composite实现的共同接口尽量用抽象类实现,可以将一些具体类别不能实现的方法设置为默认抛出异常(headfirst作者提倡以抛异常的方式处理,如果需要在调用处理时判断节点类型,就与模式的抽象初衷违背了)

网上找的一个杀毒软件杀毒例子

1.抽象leaf和组合对象的公共接口

abstract class AbstractFile {  
    public void add(AbstractFile file){
        System.out.println("对不起,不支持该方法!");  
    }  
    public abstract void remove(AbstractFile file){
        System.out.println("对不起,不支持该方法!");  
    }    
    public abstract AbstractFile getChild(int i){
        System.out.println("对不起,不支持该方法!");  
    }   
    public abstract void killVirus(); //所有类型都会进行杀毒 
}  

2.分别实现每一种节点

  • 图片类型(<b>leaf</b>)
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 + "'进行杀毒");  
    }  
}  
  • 文本文档(<b>leaf</b>)
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 + "'进行杀毒");  
    }  
}  
  • 视频(<b>leaf</b>)
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 + "'进行杀毒");  
    }  
}  
  • 文件夹(<b>composite</b>)
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 fileList.get(i);  
    }  
      
    public void killVirus() {   //关键代码。。。
        System.out.println("****对文件夹'" + name + "'进行杀毒");  //模拟杀毒  
          
        //递归调用成员构件的killVirus()方法  
        for(AbstractFile obj : fileList) {  
            obj.killVirus();  
        }  
    }  
}  

3.客户端测试类

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'进行杀毒


*/

4.如果不使用组合模式怎么实现

文件夹:

//文件夹类  
class Folder {   //没有实现共同的接口
    private String name;  
    /*
        需要定义各种类型的子节点的存储,区别对待
    */
    //定义集合folderList,用于存储Folder类型的成员  
    private ArrayList<Folder> folderList = new ArrayList<Folder>();  
    //定义集合imageList,用于存储ImageFile类型的成员  
    private ArrayList<ImageFile> imageList = new ArrayList<ImageFile>();  
    //定义集合textList,用于存储TextFile类型的成员  
    private ArrayList<TextFile> textList = new ArrayList<TextFile>();  
      
    public Folder(String name) {  
        this.name = name;  
    }  
    /*
        以下的所有操作都必须区别对待
    */  
    //增加新的Folder类型的成员  
    public void addFolder(Folder f) {  
        folderList.add(f);  
    }  
      
    //增加新的ImageFile类型的成员  
    public void addImageFile(ImageFile image) {  
        imageList.add(image);  
    }  
      
    //增加新的TextFile类型的成员  
    public void addTextFile(TextFile text) {  
        textList.add(text);  
    }  
          
    //需提供三个不同的方法removeFolder()、removeImageFile()和removeTextFile()来删除成员,代码省略  
  
    //需提供三个不同的方法getChildFolder(int i)、getChildImageFile(int i)和getChildTextFile(int i)来获取成员,代码省略  
  
    /*
      每一种类型都要单独去调用杀毒
    */
    public void killVirus() {  
        System.out.println("****对文件夹'" + name + "'进行杀毒");  //模拟杀毒  
          
        //如果是Folder类型的成员,递归调用Folder的killVirus()方法  
        for(Folder obj : folderList) {  
            obj.killVirus();  
        }  
          
        //如果是ImageFile类型的成员,调用ImageFile的killVirus()方法  
        for(ImageFile obj : imageList) {  
            obj.killVirus();  
        }  
          
        //如果是TextFile类型的成员,调用TextFile的killVirus()方法  
        for(TextFile obj : textList) {  
            obj.killVirus();  
        }  
    }   
}  

<b>当然其他的原子节点也没有实现公共接口</b>
下面看客户端调用:

class Client {  
    public static void main(String args[]) {  
        Folder folder1,folder2,folder3;  
        folder1 = new Folder("Sunny的资料");  
        folder2 = new Folder("图像文件");  
        folder3 = new Folder("文本文件");  
          
        ImageFile image1,image2;  
        image1 = new ImageFile("小龙女.jpg");  
        image2 = new ImageFile("张无忌.gif");  
          
        TextFile text1,text2;  
        text1 = new TextFile("九阴真经.txt");  
        text2 = new TextFile("葵花宝典.doc");  
          
        folder2.addImageFile(image1);  
        folder2.addImageFile(image2);  
        folder3.addTextFile(text1);  
        folder3.addTextFile(text2);  
        folder1.addFolder(folder2);  
        folder1.addFolder(folder3);  
          
        folder1.killVirus();  
    }  
}  

1.文件夹类Folder的设计和实现都非常复杂,需要定义多个集合存储不同类型的成员,而且需要针对不同的成员提供增加、删除和获取等管理和访问成员的方法,存在大量的冗余代码,系统维护较为困难;
2.由于系统没有提供抽象层,客户端代码必须有区别地对待充当容器的文件夹Folder和充当叶子的ImageFile和TextFile,无法统一对它们进行处理;客户端要构造这个树特别复杂,只有folde类型才有add接口
3.系统的灵活性和可扩展性差,如果需要增加新的类型的叶子和容器都需要对原有代码进行修改,例如如果需要在系统中增加一种新类型的视频文件VideoFile,则必须修改Folder类的源代码,否则无法在文件夹中添加视频文件。

相关文章

  • 设计模式:组合模式 职责链模式

    组合模式 职责链模式 组合模式 组合模式将对象组合成树形结构,以表示“部分-整体”的层次结构。 在组合模式的树形结...

  • 第4章 结构型模式-组合模式

    一、组合模式简介 二、组合模式的优缺点 三、组合模式的使用场景 、组合模式的实例

  • 组合模式(统一叶子与组合对象)

    目录 从生活场景出发,映射组合模式 组合模式的理论概念 组合模式的实现 组合模式在源码中的应用 组合 “优于” 继...

  • 组合模式

    1. 组合模式 1.1 组合模式的定义 组合模式(Composite): 又称部分-整体模式, 将对象组合成树形结...

  • 组合模式

    设计模式系列7--组合模式 《Objective-c 编程之道 iOS 设计模式解析》 - 组合模式 常见组合模式...

  • 设计模式 | 组合模式及典型应用

    本文的主要内容: 介绍组合模式 示例 组合模式总结 源码分析组合模式的典型应用java.awt中的组合模式Java...

  • 组合模式

    一、组合模式介绍 二、组合模式代码实例

  • 组合模式

    设计模式之组合模式 什么是组合模式? 组合模式允许你将对象组合成树形结构来表现”部分-整体“的层次结构,使得客户以...

  • 15、组合模式(Composite Pattern)

    1. 组合模式 1.1 简介   Composite模式,即组合模式,又叫部分整体模式。Composite模式将对...

  • 组合模式原型解析

    组合模式定义: 组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象...

网友评论

      本文标题:组合模式

      本文链接:https://www.haomeiwen.com/subject/qdehnttx.html