设计模式的艺术 结构性模式之组合模式

不懂使用为学过,说出用途,绘制结构为了解,不会灵活使用基本等于没学。

前言

树形结构在软件中随处可见,比如系统中的目录结构,应用软件中的菜单,如何运用面向对象的方式来处理这种树形结构是组合模式需要解决的问题。组合模式通过一种巧妙的设计方案来使得用户可以一致性的处理整个树形结构或者树形结构的一部分,也可以一致的处理树形结构中的叶子节点。

什么是组合模式  Composite Pattern

组合多个对象形成树形结构以表示具有"整体-部门"关系的层次结构。组合模式对单个对象(叶子对象)和组合对象(容器对象)的使用具有一致性,所有又被称之为"整体-部分"模式,它是一种结构性模式

组合模式的优点

(1)、可以清楚的定义分层次的复杂对象,表示对象的全部或部分层次,她让客户端忽略了层次的差异,方便对于整个层次结构进行控制

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

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

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

组合模式的缺点

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

组合模式的使用场景

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

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

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

组合模式的具体实现

项目结构

抽象构件

package com.company;

//抽象文件类:抽象构件
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();
}

容器构件

package com.company;

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;
    }

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

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

    @Override
    public AbstractFile getChild(int i) {

        return (AbstractFile) fileList.get(i);
    }

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

        }

叶子构件

package com.company.file;

import com.company.AbstractFile;

//图像文件类:叶子构件
public class ImageFile extends AbstractFile {
    private String name;

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

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

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

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

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

    }
}
package com.company.file;

import com.company.AbstractFile;

public class TextFile extends AbstractFile {
    private String name;

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

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

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

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

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

测试类

package com.company;

import com.company.file.ImageFile;

public class Client {

    public static void main(String[] args) {
   // write your code here
        //针对抽象构件编程
        AbstractFile file1,file2,file3,file4,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 ImageFile("九阴真经.txt");
        file4=new ImageFile("葵花宝典.doc");

        folder1.add(file1);
        folder2.add(file2);
        folder3.add(file3);
        folder4.add(file4);
        //从"Sunny的资料"节点开始进行杀毒
        folder1.killVirus();
        folder2.killVirus();
        folder3.killVirus();
        folder4.killVirus();
    }
}

转载请注明出处,掌声送给社会人

猜你喜欢

转载自blog.csdn.net/SCDN_CP/article/details/82878807
今日推荐