组合模式的简单使用

前言

组合模式也称为整体部分模式,其结构比较简单,类似于组织结构的树状图,就像我所在的公司,属于集团下面的子公司,集团包括行政部门和财务,而我们公司也有这样两个部门,更加形象的说,组合模式最容易理解的是电脑的磁盘文件夹,文件夹里面可以有各类文件,也还可以有子文件夹,而子文件夹里面也同样可以有这些东西。关于定义则套用百度百科:组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。掌握组合模式的重点是要理解清楚 “部分/整体” 还有 ”单个对象“ 与 “组合对象” 的含义。

角色扮演

Component:抽象根节点,为组合模式中的对象声明接口,在适当情况可以实现类的接口,从而省掉接口类。声明一个接口用于访问和管理Component的子节点,可以再递归结构中定义一个接口,用于访问一个父节点,并在合适的时候实现这个接口。用简单的话来说,这个就是root根节点,然后子节点可以包含它,就像文件夹,子文件夹可以还有文件夹。
Composite:定义有子节点的那些枝干节点的行为,存储子节点,在Component接口中实现与子节点有关的操作。用文件夹举例:该对象就是一个子文件夹。
Leaf:在组合中表示叶子节点对象,叶子节点不在具有子节点,很好理解,这就相当于文件夹里面的各类文件。

适用场景

在表示对象的“部分-整体”结构时。

DEMO

因为一直拿文件夹举例,那我们就抽象一个文件夹的实例:
一个根目录下分为文件夹和普通文件,其都继承于File类,为了不违背依赖倒置原则,我们把文件夹的方法抽象到父类,由子类判断执行相关操作:

package com.demo.composite;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by italkbb on 2017/12/29.
 */

public abstract class File {
    // 无论文件和文件夹都要名字
    private String name;
    // 存文件夹下所有元素
    protected List<File> files = new ArrayList<>();

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

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name = name ;
    }

    /**
     * 添加文件或者文件夹
     * @param file
     */
    public abstract void addFile(File file);

    /**
     * 删除文件或者文件夹
     * @param file
     */
    public abstract void removeFile(File file);

    /**
     * 输出文件结构
     */
    public abstract void display();

    /**
     * 获取文件夹下所有文件和文件夹
     * @return
     */
    public abstract List<File> getFiles();
}

其次我们要写两个文件,文件夹对应Composite:

package com.demo.composite;

import java.util.List;

/**
 * Created by italkbb on 2017/12/29.
 */

public class Folder extends File {

    public Folder(String name) {
        super(name);
    }

    @Override
    public void addFile(File file) {
        files.add(file);
    }

    @Override
    public void removeFile(File file) {
        files.remove(file);
    }

    @Override
    public void display() {
        System.out.print(getName() + "(");
        for (File file:files){
            System.out.print(file.getName() + ";");
            if (file instanceof Folder){
                file.display();
            }
        }
        System.out.print(")");
    }

    @Override
    public List<File> getFiles() {
        return files;
    }
}

以及普通文件,普通文件无权执行一些文件夹的操作,所以抛出异常,这个相当于Leaf:

package com.demo.composite;

import java.util.List;

/**
 * Created by italkbb on 2017/12/29.
 */

public class NormalFile extends File {
    public NormalFile(String name) {
        super(name);
    }

    @Override
    public void addFile(File file) {
        throw new UnsupportedOperationException("普通文件不支持");
    }

    @Override
    public void removeFile(File file) {
        throw new UnsupportedOperationException("普通文件不支持");
    }

    @Override
    public void display() {
        System.out.print(getName());
    }

    @Override
    public List<File> getFiles() {
        throw new UnsupportedOperationException("普通文件不支持");
    }
}

最后我们简单看一下使用的情况:

package com.demo.composite;

/**
 * Created by italkbb on 2017/12/29.
 */

public class Client {
    public static void main(String[] args){
        // 创建根目录
        File rootFile = new Folder("Root");

        // 在根目录下创建几个文件和文件夹
        rootFile.addFile(new NormalFile("README.md"));
        rootFile.addFile(new NormalFile(".gitignore"));
        rootFile.addFile(new NormalFile("build.gradle"));

        File homeFile = new Folder("app");
        homeFile.addFile(new NormalFile("Test.java"));

        rootFile.addFile(homeFile);
    }
}

后记

组合模式能够很清楚的定义分层次的复杂对象,使用的时候就可以忽略其层次结构,或者说弱化层次机构吧。组合模式使设计变得更加抽象,对象的业务规则如果很复杂,那么实现起来这个模式就变得很难,而且不是所有的方法都与叶子对象子类都有关联。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值