下面是正文
组合模式使用户对单个对象和组合对象的使用具有一致性。
屏蔽了容器对象与单个对象在使用时的差异,为客户提供统一的操作接口,从而降低客户代码与被调用对象的耦合关系,方便系统维护与扩展。
当需求中体现部分与整体层次结构时,以及希望用户可以忽略组合对象与单个对象不同时,统一德使用组合结构中的所有对象时,可考虑使用组合模式。
组合模式让客户可以一致的使用组合结构对象和单个对象。
可以清楚的定义分层次的组合对象。
组合模式有透明式组合模式和安全式组合模式两种形式。
现在我们电脑上有一个文件管理器,里面包含了a文件夹和b文件以及c文件,同时a文件夹中也包含了aa文件夹和a1文件,aa文件夹中又包含了aaa文件夹和aa1文件。
这里我们(Client)就可以使用组合模式统一对文件管理器中的文件以及文件夹操作。
透明式组合模式
/**
* 抽象构件
*
* 这里是整个文件管理器的所有操作
* */
public interface Component {
void add(Component c);
void delete(Component c);
Component getChild(int i);
void opereat();
}
/**
* 文件管理器中的文件
*
* 即 树叶 leaf
* */
public class File implements Component {
private String name;
protected File(String name){
this.name = name;
}
@Override
public void add(Component c) {
System.out.println("文件不支持添加");
}
@Override
public void delete(Component c) {
System.out.println("文件不支持删除");
}
@Override
public Component getChild(int i) {
System.out.println("文件不支持此方法");
return null;
}
@Override
public void opereat() {
System.out.printf("--------访问 %s 文件\n",name);
}
}
/**
* 文件管理器中的文件夹
*
* 即 树枝构件
* */
public class Folder implements Component {
private String message;
private List files = new ArrayList<>();
protected Folder(String message){
this.message = message;
}
@Override
public void add(Component c) {
files.add(c);
}
@Override
public void delete(Component c) {
files.remove(c);
}
@Override
public Component getChild(int i) {
return files.get(i);
}
@Override
public void opereat() {
System.out.printf("----访问 %s 文件夹\n", message);
for (Component component : files) {
component.opereat();
}
}
}
/**
* 组合模式主入口
*
* 文件管理器client
* */
public class ComponentPatternMain {
public static void main(String[] main){
Component fileManager = new Folder("文件管理器");
Component a = new Folder("a"); //a文件夹
Component b = new File("b"); //b文件
Component c = new File("c"); //c文件
fileManager.add(a);
fileManager.add(b);
fileManager.add(c);
Component aa = new Folder("aa"); //aa文件夹
Component a1 = new File("a1"); //a1文件
a.add(aa);
a.add(a1);
Component aaa = new Folder("aaa");//aaa文件夹
Component aa1 = new File("aa1");//aa1文件
aa.add(aaa);
aa.add(aa1);
fileManager.opereat();
}
}
输出
从上面可以看出,文件(leaf)不支持添加、删除、得到子文件的操作,但是依然对其方法进行了实现,我们不得不提供错误的方法及提示。
安全式组合模式
/**
* 安全组合模式
*
* 这种方式是把抽象构件中不声明添加,删除等对构件进行操作管理的方法去除,让他们各自实现自己的方法
*
* 把共有的操作抽象出来
* */
public interface SafeComponent {
//文件和文件夹共有的操作
void operate();
}
/**
* 安全组合模式
*
* 树枝
* */
public class SafeFolder implements SafeComponent{
private String folderName;
private List safeComponentList = new ArrayList<>();
protected SafeFolder(String folderName){
this.folderName = folderName;
}
/*对于文件夹(树枝)来说,除了实现抽象构件的方法之外,还需要自己提供add,remove等操作*/
@Override
public void operate() {
System.out.printf("----访问 %s 文件夹\n",folderName);
for (SafeComponent safeComponent : safeComponentList){
safeComponent.operate();
}
}
protected void add(SafeComponent component){
this.safeComponentList.add(component);
}
protected void remove(SafeComponent component){
this.safeComponentList.remove(component);
}
protected SafeComponent getChild(int i){
return this.safeComponentList.get(i);
}
}
/**
* 安全组合模式
*
* 树叶 leaf
* */
public class SafeFile implements SafeComponent{
private String fileName;
protected SafeFile(String fileName){
this.fileName = fileName;
}
/*对于没有add,remove方法的树叶来说,只需要实现抽象构件即可*/
@Override
public void operate() {
System.out.printf("--------访问 %s 文件\n",fileName);
}
}
/**
* 组合模式主入口
*
* 文件管理器client
* */
public class ComponentPatternMain {
public static void main(String[] main){
//安全组合模式
SafeFolder safeFileManager = new SafeFolder("安全文件管理器");
SafeFolder sa = new SafeFolder("sa");
SafeComponent sb = new SafeFile("sb");
SafeComponent sc = new SafeFile("sc");
safeFileManager.add(sa);
safeFileManager.add(sb);
safeFileManager.add(sc);
SafeFolder saa = new SafeFolder("saa");
SafeComponent sa1 = new SafeFile("sa1");
sa.add(saa);
sa.add(sa1);
SafeFolder saaa = new SafeFolder("saaa");
SafeComponent saa1 = new SafeFile("saa1");
saa.add(saaa);
saa.add(saa1);
safeFileManager.operate();
}
}
[Java]
设计模式源码