组合模式和享元模式

组合模式和享元模式

一、组合模式

组合模式是一种是数据结构或算法的抽象,将一组对象组织成树形结构,将单个对象和组合对象都看做树中的节点,以统一处理逻辑,并且它利用树形结构的特点,递归地处理每个子树,依次简化代码实现。使用组合模式的前提在于,你的业务场景必须能够表示成树形结构,有整体和部分的关联关系。所以,组合模式的应用场景也比较局限,它并不是一种很常用的设计模式。——摘自王争《设计模式之美》

比如我们可以通过代码实现下面这种树形结构的遍历:

在这里插入图片描述在这里插入图片描述

首先创建抽象类

/**
 * 文件抽象类
 */
@Data
public abstract class File {

    /**
     * 文件名称
     */
    public String fileName;

    /**
     * 构造方法
     */
    File(String fileName) {
        this.fileName = fileName;
    }

    /**
     * 抽象方法:浏览
     */
    public abstract void scan();
}

然后创建视频和文本类,这里只展示视频类,文本与其一样

/**
 * 视频文件
 */
public class VedioFile extends File{

    public VedioFile(String fileName) {
        super(fileName);
    }

    @Override
    public void scan() {
        System.out.println("视频文件:" + fileName);
    }
}

然后创建视频文件夹,文本文件夹与其一样

/**
 * 视频文件夹:包含所有视频文件
 */
public class FolerVedio extends File{

    /**
     * 所有视频文件集合
     */
    private List<File> vedioFiles;

    /**
     * 构造方法,将文件夹名称传入
     */
    public FolerVedio(String folderName) {
        super(folderName);
        this.vedioFiles = Lists.newArrayList();
    }

    /**
     * 浏览方法的实现类
     */
    @Override
    public void scan() {
        for (File vedioFile : vedioFiles) {
            vedioFile.scan();
        }
    }

    /**
     * 文件添加
     */
    public void addFile(File file) {
        vedioFiles.add(file);
    }

    /**
     * 文件删除
     */
    public boolean del(File file) {
        return vedioFiles.remove(file);
    }
}

最后创建一个大文件夹

/**
 * 大文件夹
 */
public class Folder extends File {

    private List<File> files;

    public Folder(String folderName) {
        super(folderName);
        this.files = Lists.newArrayList();
    }

    /**
     * 文件添加
     */
    public void addFile(File file) {
        files.add(file);
    }

    /**
     * 文件删除
     */
    public boolean del(File file) {
        return files.remove(file);
    }

    @Override
    public void scan() {
        for (File file : files) {
            file.scan();
        }
    }
}

测试打印结果:

@RunWith(JUnit4.class)
public class CombinationTest {

    @Test
    public void testCombination() {

        //大文件夹
        Folder folder = new Folder("大文件夹");

        //创建多个视频文件夹并存入多个视频文件
        for (int i = 0; i < 2; i++) {
            FolerVedio folerVedio = new FolerVedio("文件夹vedio-" + i);
            for (int j = 0; j < 5; j++) {
                VedioFile vedioFile = new VedioFile("视频文件{"+ i +"-"+ j + "}");
                folerVedio.addFile(vedioFile);
            }
            folder.addFile(folerVedio);
        }

        //创建多个文本文件夹并存入多个文本文件
        for (int i = 0; i < 2; i++) {
            FolerText folerText = new FolerText("文件夹text-" + i);
            for (int j = 0; j < 2; j++) {
                TextFile textFile = new TextFile("文本文件{"+ i +"-"+ j + "}");
                folerText.addFile(textFile);
            }
            folder.addFile(folerText);
        }

        //文件浏览
        folder.scan();
    }
}

//打印结果:
视频文件:视频文件{0-0}
视频文件:视频文件{0-1}
视频文件:视频文件{0-2}
视频文件:视频文件{0-3}
视频文件:视频文件{0-4}
视频文件:视频文件{1-0}
视频文件:视频文件{1-1}
视频文件:视频文件{1-2}
视频文件:视频文件{1-3}
视频文件:视频文件{1-4}
文本文件:文本文件{0-0}
文本文件:文本文件{0-1}
文本文件:文本文件{1-0}
文本文件:文本文件{1-1}

二、享元模式

所谓“享元”,顾名思义就是被共享的单元。享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象。具体来讲,当一个系统中存在大量重复对象的时候,如果这些重复的对象是不可变对象,我们就可以利用享元模式将对象设计成享元,在内存中只保留一份实例,供多处代码引用。这样可以减少内存中对象的数量,起到节省内存的目的。实际上,不仅仅相同对象可以设计成享元,对于相似对象,我们也可以将这些对象中相同的部分(字段)提取出来,设计成享元,让这些大量相似对象引用这些享元。这里我稍微解释一下,定义中的“不可变对象”指的是,一旦通过构造函数初始化完成之后,它的状态(对象的成员变量或者属性)就不会再被修改了。所以,不可变对象不能暴露任何 set() 等修改内部状态的方法。之所以要求享元是不可变对象,那是因为它会被多处代码共享使用,避免一处代码对享元进行了修改,影响到其他使用它的代码。——摘自王争《设计模式之美》

在实际开发中,一般都会使用枚举类来进行各种判断和处理。

/**
 * 商家类型
 */
@Getter
public enum AgencyTypeEnum {
    TO_B(1, Sets.newHashSet("alibaba", "tencent"), "企业"),
    TO_C(2, Sets.newHashSet("MaSaKi"), "个人");

    /**
     * 代号
     */
    private int code;

    /**
     * set集合:包含商家名称
     */
    private Set<String> agencyNames;

    /**
     * 描述
     */
    private String desc;

    /**
     * 构造方法
     */
    AgencyTypeEnum(int code, Set<String> agencyNames, String desc) {
        this.code = code;
        this.agencyNames = agencyNames;
        this.desc = desc;
    }
}

这其实就是一种享元模式的应用,非常简单,核心就是要减小内存空间的消耗。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值