目录
1 介绍
部分整体模式,是用于把一组相似的对象当作一个单一的对象。
2 例子
这样的情况非常使用于文件夹存放文件的情况,文件夹可以多级,如果为每级文件夹都定义一个类的话成本是非常高的。
2.1 文件夹(文件)抽象父类
//抽象父类
abstract class FileFolder {
//展示一下这个文件夹
public abstract void show();
//添加
public abstract void add(FileFolder fileFolder);
//移除
public abstract void remove(FileFolder fileFolder);
}
注意:该父类标识某一级文件夹,有一些自己的方法,比如显示该目录下所有的文件夹或者文件等等,删除等等,他也不知道自己下面还有多少级,反正提供了一个把自己类型的作为形参的抽象方法。
2.2 添加一个接口适配器(可选)
//添加一个接口适配器
abstract class FileFolderAdapter extends FileFolder {
@Override
public void show() {
}
@Override
public void add(FileFolder fileFolder) {
}
@Override
public void remove(FileFolder fileFolder) {
}
}
接口适配器前面说到了,就是接口的有些方法想实现,有些不想,就是采用了这样一个方式,我仅仅是为了捡便宜,在叶子节点的时候不想实现add和remove方法。
2.3 叶子节点的实现
//叶子节点
class Leaf1 extends FileFolderAdapter {
@Override
public void show() {
System.out.println("视频");
}
}
class Leaf2 extends FileFolderAdapter {
@Override
public void show() {
System.out.println("图片");
}
}
class Leaf3 extends FileFolderAdapter {
@Override
public void show() {
System.out.println("音频");
}
}
定义了三种叶子节点,可以表示不同的文件类型。
2.4 非叶子节点
//非叶子节点
class FileFolderUse extends FileFolderAdapter{
//定义一个存储文件的容器
List<FileFolder> list=new ArrayList<>();
@Override
public void show() {
System.out.println("文件夹");
for (FileFolder i:list){
i.show();
}
}
@Override
public void add(FileFolder fileFolder) {
list.add(fileFolder);
}
@Override
public void remove(FileFolder fileFolder) {
list.remove(fileFolder);
}
}
存储fileFolder的容器可以任意,数组、集合、列表、链表、map都可以。
2.5 测试主类
public class Main {
public static void main(String[] args) {
//先定义叶子节点
FileFolder leaf1=new Leaf1();
FileFolder leaf2=new Leaf2();
FileFolder leaf3=new Leaf3();
FileFolder leaf4=new Leaf3();
//定义一个文件夹B把它放进去
FileFolder B=new FileFolderUse();
B.add(leaf1);
B.add(leaf2);
B.add(leaf3);
B.add(leaf4);
//再定义一个文件夹
FileFolder A=new FileFolderUse();
A.add(B);
//显示
A.show();
}
}
3 例子升华
组合模式的最精髓的在于其抽象父类的设计,里面定义的操作方法的参数是抽象父类的数据类型,很好的实现了不同类型对象的统一操作和递归操作。
4 总结
4.1 核心角色
- 抽象父类:定义了一种统一的数据类型,及其递归操作。
- 叶子节点实现:叶子节点的部分方法实现会不一样。
- 非叶子节点的实现:非叶子节点会实现所有方法。
4.2 核心代码结构
抽象父类的设计,那种自己操作自己的设计思路值得学习。