Java设计模式-结构型模式设计模式-组合模式

Java设计模式-结构型模式设计模式-组合模式

从这一专栏开始将学习设计模式,上课学习和自己总结归纳的笔记将总结出来供大家参考。
参考书籍:《设计模式就该这样学》

其他文章:

Java设计模式-UML类图Java设计模式-七大架构设计原则-开闭原则
Java设计模式-七大架构设计原则-依赖倒置原则Java设计模式-七大架构设计原则-单一职责原则
Java设计模式-七大架构设计原则-接口隔离原则Java设计模式-七大架构设计原则-最少知道原则(迪米特法则)
Java设计模式-七大架构设计原则-里氏替换原则和合成复用原则Java设计模式-创建型设计模式-简单工厂模式
Java设计模式-创建型设计模式-工厂方法模式(工厂模式)Java设计模式-创建型设计模式-抽象工厂模式
Java设计模式-创建型设计模式-建造者模式Java设计模式-创建型设计模式-原型模式
Java设计模式-创建型设计模式-单例模式Java设计模式-结构型设计模式-适配器模式
Java设计模式- 结构型设计模式-享元模式Java设计模式- 结构型设计模式-外观模式
Java设计模式- 结构型设计模式-桥接模式Java设计模式-结构型模式设计模式-组合模式
Java设计模式-行为型设计模式-观察者模式

一、结构型设计模式

在GOF23种设计模式中,有三种类型的设计模式,分别是:创建型设计模式、结构型设计模式、行为型设计模式

结构型设计模式有:代理模式、适配器模式、桥接模式、装饰模式、外观模式、享元模式、组合模式 7 种结构型模式。

​ 类结构型模式:关心类的组合,由多个类组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系。

​ 对象结构型模式:关心类与对象的组合,通过关联关系,在一个类中定义另外一个类的实例对象,然后通过该对象调用相应的方法。

二、组合模式

1.组合模式定义

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

结构型设计模式有:代理模式、适配器模式、桥接模式、装饰模式、外观模式、享元模式、组合模式 7 种结构型模式。

2.组合模式的角色:

抽象构件(Component):叶子构件与容器构件共同继承的父类或者是共同实现的接口,该角色中包含所有子类共有方法的声明和实现,在抽象构件中定义了管理子构件的方法,新增构件、删除构件、获取构件。
叶子构件(Leaf):表示叶子节点,没有子节点,对于继承父类的管理子节点的方法以抛出异常的方式处理。类似于文件
容器构件(Composite):表示容器节点,包含子节点,子节点可以是容器节点也可以是叶子节点,其提供一个集合来对子节点进行维护,以迭代的方式对子节点进行处理。类似于文件夹

3.组合模式的特点

优点:

节点自由增加。使用了组合模式后,如果想增加一个树枝节点、树叶节点十分简单,只要找到它的父节点就成,非常容易扩展,符合开闭原则,有利于后期维护。

缺点:

树枝树叶直接使用了实现类,这在面向接口编程上是很不恰当的,与依赖倒置原则冲突,限制了接口的影响范围。

适用环境

1.想表示对象的部分-整体层次结构(树形结构)

2.想用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

4.组合模式的类图

在这里插入图片描述

5.组合模式的代码实现

5.1具体案例:

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

类图如下:

在这里插入图片描述

具体代码实现:

1.抽象构件AbstractFile

public abstract class AbstractFile {

    private String filePath;

    public String getFilePath() {
        return filePath;
    }

    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }

    public abstract void Add(AbstractFile file);
    public abstract void Remove(AbstractFile file);
    public abstract AbstractFile GetChild(int i);
    public abstract String KillVirus();

}

2.容器构件Folder

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


    @Override
    public void Add(AbstractFile file) {
        if (file!=null){
            fileList.add(file);
        }

    }

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

    }

    @Override
    public AbstractFile GetChild(int i) {
        return fileList.get(i);
    }

    @Override
    public String KillVirus() {
        //遍历文件夹的所有文件
        for (AbstractFile abstractFile : fileList) {
            //如果文件夹下面没有文件夹就返回杀毒结果
            String result = abstractFile.KillVirus();
            if(result!=null){
                System.out.println(result);
            }
        }
        return null;
    }
}

3.叶子构件TextFile、ImageFile、VideoFile

public class ImageFile extends AbstractFile {
    private String name;

    @Override
    public void Add(AbstractFile file) {

    }

    @Override
    public void Remove(AbstractFile file) {

    }

    @Override
    public AbstractFile GetChild(int i) {
        return null;
    }

    @Override
    public String KillVirus() {
        System.out.println("对Img文件"+getFilePath()+" 开始杀毒");
        if(Math.random()<0.50){
            return "感染病毒杀毒成功";
        }
        return "文件无毒";
    }
}

public class VideoFile extends AbstractFile {
    private String name;


    @Override
    public void Add(AbstractFile file) {

    }

    @Override
    public void Remove(AbstractFile file) {

    }

    @Override
    public AbstractFile GetChild(int i) {
        return null;
    }

    @Override
    public String KillVirus() {
        System.out.println("对Video文件"+getFilePath()+" 开始杀毒");
        if(Math.random()<0.40){
            return "感染病毒杀毒成功";
        }
        return "文件无毒";
    }
}

public class TextFile extends AbstractFile {
    private String name;


    @Override
    public void Add(AbstractFile file) {

    }

    @Override
    public void Remove(AbstractFile file) {

    }

    @Override
    public AbstractFile GetChild(int i) {
        return null;
    }

    @Override
    public String KillVirus() {
        System.out.println("对Text文件"+getFilePath()+" 开始杀毒");
        if(Math.random()<0.40){
            return "感染病毒杀毒成功";
        }
        return "文件无毒";
    }
}

4.客户端测试类

public class Clinet {


    /**
     * 根据文件名判断文件类型,并返回对应的AbstractFile
     * @param filename
     * @return
     */
    private static AbstractFile getFilefromName(String filename){
        if(filename.endsWith(".doc")
                ||filename.endsWith(".docx")
                ||filename.endsWith(".xls")
                ||filename.endsWith(".txt")
                ||filename.endsWith(".doc")
                ){
            AbstractFile file=new TextFile();
            file.setFilePath(filename);
            return file;
        }

        if(filename.endsWith(".jpg")
                ||filename.endsWith(".png")
                ){
            AbstractFile file=new ImageFile();
            file.setFilePath(filename);
            return file;
        }
        if(filename.endsWith(".mp4")
                ||filename.endsWith(".mp3")
                ){
            AbstractFile file=new VideoFile();
            file.setFilePath(filename);
            return file;
        }
        return null;
    }




    /**
     * 将指定的根目录下的文件和文件夹加载到Folder对象中
     * @param rootDirectory
     * @return
     */
    private static Folder loadFilesToFolder(File rootDirectory){
        Folder rootFolder = new Folder();
        rootFolder.setFilePath(rootDirectory.getAbsolutePath());
        //返回当前目录下的文件和子目录
        File[] children=rootDirectory.listFiles();
        if(children==null){
            return null;
        }
        //遍历文件和子目录
        for (File child : children) {
            if(child.isDirectory()){
                //child是一个子目录,则递归生成Folder对象
                Folder folder = loadFilesToFolder(child);
                rootFolder.Add(folder);
            }
            if(child.isFile()){
                AbstractFile file = getFilefromName(child.getName());
                rootFolder.Add(file);
            }
        }
        return rootFolder;
    }

    public static void main(String[] args) {
        //对D盘下的文件杀毒
        File rootfile = new File("D:\\");
        Folder folder = loadFilesToFolder(rootfile);
        folder.KillVirus();
    }

}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值