设计模式-组件模式

组件模式

概念

一个东西,既可以作为其他容器中的一项,同时自己也可以作为容器存储其他东西,其他东西可以是普通的内容,内容不能作为容器了,也可以是容器,而这个东西就是抽象的最上层。

角色

  • Leaf
    叶子,即内容,最小的原子
  • Composite
    容器,可以存储容器和内容
  • Component
    容器和内容被视作同一超类下的子类,这个超类就是组件
  • Client
    调用者

案例

模拟文件系统

  • Leaf
    File(文件:实类)
  • Composite
    Folder(文件夹:实类),文件夹中可以加入文件或者子文件夹
  • Component
    Entry(条目:抽象类,文件,文件夹都算作是条目)
  • Client
    调用者(Main.java)

Entry

  • 条目都有名字,因此抽象条目直接具备name属性
  • 至于条目的大小,文件是自身的大小,文件夹则是目录下所有文件大小的集合,逻辑上不太一样,还是交给子类去拓展吧,这里只声明一个获取size的方法
  • list方法则是打印条目内所有条目信息(带上路径和条目名)
package com.example.composite.example_folder;

public abstract class Entry {
    protected String name;

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

    public String getName(){
        return name;
    }
    public abstract int getSize();

    public void list(){
        list("");
    }

    protected abstract void list(String prefix);	//路径前缀

    @Override
    public String toString(){
        return getName() + "(" + getSize() + " kb)";
    }
}

File

文件:

  • 新增size属性,构造时给文件设定大小
  • list方法,打印自己的条目信息,也就是name和size,带上单位kb
package com.example.composite.example_folder;

public class File extends Entry {
    private int size;

    public File(String name, int size) {
        super(name);
        this.size = size;
    }

    @Override
    public int getSize() {
        return size;
    }

    @Override
    protected void list(String prefix) {
        System.out.println(prefix + "/" + this);
    }
}

Folder

文件夹:

  • 私有一个条目列表
  • 有一个add方法,往自己的条目列表加入一个条目
  • 获取size方法,遍历条目列表,累加所有条目的size,如果某个子条目也是文件夹,就递归下去获取size,如果是文件,就能直接拿到size
  • list方法,遍历打印条目列表中每个条目的信息,原理类似获取size
package com.example.composite.example_folder;

import java.util.ArrayList;

public class Folder extends Entry {

    private ArrayList<Entry> entries = new ArrayList();

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

    @Override
    public int getSize() {
        int size = 0;
        for ( Entry entry: entries) {
            size += entry.getSize();
        }
        return size;
    }

    public Entry add(Entry entry) {
        entries.add(entry);
        return this;
    }

    @Override
    protected void list(String prefix) {
        System.out.println(prefix + "/" + this);
        for ( Entry entry: entries) {
            entry.list(prefix + "/" + name);
        }
    }
}

Main.java

package com.example.composite;

import com.example.composite.example_folder.File;
import com.example.composite.example_folder.Folder;

public class Main {

    public static void main(String[] args) {
        Folder folder_root = new Folder("root");

        Folder folder_bin = new Folder("bin");
        folder_root.add(folder_bin);

        Folder folder_vi = new Folder("vi");
        folder_bin.add(folder_vi);
        Folder folder_latex = new Folder("latex");
        folder_bin.add(folder_latex);

        Folder folder_tmp = new Folder("tmp");
        folder_root.add(folder_tmp);

        Folder folder_usr = new Folder("usr");
        folder_root.add(folder_usr);

        Folder folder_evanp = new Folder("evanp");
        folder_usr.add(folder_evanp);

        File file_readme_md = new File("readme.md", 200);
        folder_evanp.add(file_readme_md);

        folder_root.list();
    }
}

Output

D:\Develop-Environment\Java\jdk-1.8\bin\java.exe ...

/root(200 kb)
/root/bin(0 kb)
/root/bin/vi(0 kb)
/root/bin/latex(0 kb)
/root/tmp(0 kb)
/root/usr(200 kb)
/root/usr/evanp(200 kb)
/root/usr/evanp/readme.md(200 kb)

Process finished with exit code 0

应用场景

使用Composite模式可以使得容器与内容具有一致性,即将多个对象结合在一起,当作一个对象处理,访问容器的内容时,自然的形成了递归结构,通常来说,树形结构都使用Composite模式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值