设计模式之复合模式
来源:互联网 发布:胡一帆写字软件 编辑:程序博客网 时间:2024/05/16 01:40
DesignPattern之复合模式
1. Definition
组合模式允许将对象组合成树形结构来表现“整体 / 部分”层次结构,能让客户以==一致==的方式处理个别对象及对象组合(一视同仁)
2. 分析(Head First Design Pattern p358)
根据 Head First Design Pattern 第358页的uml图来分析:
类图当中有三个类,一个是Component(节点的统一接口),它的目的是为了统一节点的操作。
接下来的两个实现类,一个则是非叶子节点(Composite),它可以有子节点,子节点可以是Leaf,也可以是Composite。
另外一个则是叶子节点(Leaf),它不能含有子节点。
客户操作的Component,也就是说,无论是Leaf还是Composite,在客户看来其实都是Component。那如何让客户将Composite和Leaf一视同仁呢?很简单,只要让Component中同时包含Leaf和Composite的方法就可以了。
- 那现在问题又来了,有些方法是Leaf或者Composite独有的,但是Leaf或者Composite都实现了Component接口,必须实现全部方法,然而让Leaf实现Composite独有的方法并没有什么意义。如何解决这个问题呢?——> 解决的方案有好多种,说一种书上给出的方案:让这些方法抛出
UnsupportedOperationException
就可以了。
3. 例子
就拿电脑的文件系统来举例子:文件夹是一个文件,单个的文件,比如“.avi”, ”.txt”也是文件,所以可以让它们都实现一个MyFile
接口。它们之间的共性有好多,比如都可以进行删除操作。但是删除文件跟删除文件夹是有区别的:
- 删除文件:只需要删除当前文件就可以了
- 删除文件夹:必须要删除这个文件夹里面的所有文件和文件夹
那么组合模式的一致性(客户能一视同仁的地方)就体现在: 客户不需要知道当前操作的是单个文件还是文件夹,客户只知道要进行删除文件(这里的文件指的是接口MyFile
)操作就可以了
- 接口
MyFile
~~~java
package composite;public interface MyFile { public void delete(); public String getName(); public void createNewFile(String name); // Only for folder public void deleteFile(String name); // only for folder public MyFile getMyFile(int index); public void show();}
~~~
- 文件夹 Folder:
Folder中有一个集合,用来保存文件夹里面的单个文件及子文件夹
~~~java
package composite;import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class Folder implements MyFile { private String name; private MyFile folder; private List<MyFile> files; public Folder(String name) { this(name, null); } public Folder(String name, MyFile folder) { this.name = name; this.folder = folder; this.files = new ArrayList<MyFile>(); } @Override public void delete() { System.out.println("delete subfiles...\n"); for (Iterator<MyFile> i = this.files.iterator(); i.hasNext();) { i.next(); i.remove(); } System.out.println("finished deleting subfiles!\n"); System.out.println("---Deleted [" + this.name + "]---\n"); } @Override public String getName() { return this.name; } @Override public void createNewFile(String name) { if (name.contains(".")) { files.add(new File(name, this)); } else { files.add(new Folder(name, this)); } } @Override public void deleteFile(String name) { for (MyFile file : this.files) { if (file.getName().equals(name)) { this.files.remove(file); System.out.println("---Deleted [" + file.getName() + "]---\n"); break; } } } @Override public MyFile getMyFile(int index) { return this.files.get(index); } @Override public void show() { System.out.println("------" + this.name + "------"); for (MyFile file : this.files) { file.show(); } }}
~~~
- 单个文件 File:
~~~java
package composite;public class File implements MyFile { private String name; private MyFile folder; public File(String name, MyFile folder) { this.name = name; this.folder = folder; } @Override public void delete() { this.folder.deleteFile(this.name); } @Override public String getName() { return name; } @Override public void createNewFile(String name) { throw new UnsupportedOperationException(); } @Override public void deleteFile(String name) { throw new UnsupportedOperationException(); } @Override public MyFile getMyFile(int index) { throw new UnsupportedOperationException(); } @Override public void show() { System.out.println("[" + this.name + "]"); }}
~~~
- 测试类:
~~~java
~~~package composite;public class Demo { public static void main(String[] args) { //-----------root------------------- MyFile root = new Folder("My Computer"); root.createNewFile("Disk C"); root.createNewFile("Disk D"); root.createNewFile("Disk E"); //---------Disk D-------------------- MyFile diskD = root.getMyFile(1); diskD.createNewFile("Project"); diskD.createNewFile("Movies"); //--------project-------------------- MyFile project = diskD.getMyFile(0); project.createNewFile("Test1.java"); project.createNewFile("Test2.java"); project.createNewFile("Test3.java"); //--------movies-------------------- MyFile movies = diskD.getMyFile(1); movies.createNewFile("Matrix1.avi"); movies.createNewFile("Matrix2.avi"); // print all files System.out.println("Before deletion:"); root.show(); // Now try to delete some files! System.out.println(); project.delete(); movies.deleteFile("Matrix2.avi"); System.out.println("After deletion:"); root.show(); }}
~~~
- 结果:
~~~java
Before deletion:------My Computer------------Disk C------------Disk D------------Project-------[Test1.java]-[Test2.java]-[Test3.java]------Movies-------[Matrix1.avi]-[Matrix2.avi]------Disk E------delete subfiles...finished deleting subfiles!---Deleted [Project]------Deleted [Matrix2.avi]---After deletion:------My Computer------------Disk C------------Disk D------------Project------------Movies-------[Matrix1.avi]------Disk E------
~~~
4. 思考
组合模式以牺牲单一责任原则来换取透明性(transparency)。透明性指:通过让组件的接口同时包含有一些管理Composite和Leaf的操作,客户就可以将两者一视同仁。也就是说,一个元素究竟是Composite和Leaf,对客户来说是透明的。
当然也可以采用另一种方向的设计,将接口一分为二,将责任区分开来放在不同的接口中。这样一来,设计上比较安全,但也因此失去了透明性,因为客户必须用条件语句和instanceof来判断不同类型的节点。
组合模式是一个经典的折中案例:尽管我们受到设计原则的指导,但是也需要观察某些原则对我们设计造成的影响,并故意做一些看似违反原则的设计来换取设计的平衡。
- 设计模式之复合模式
- 设计模式之复合模式
- 设计模式之复合模式
- Java 设计模式 -- 复合模式之二
- JAVA设计模式之复合模式
- 设计模式-复合模式
- IOS复合设计模式
- 设计模式之复合模式和总结篇
- 复合模式之MVC
- 复合设计模式—MVC
- 复合设计模式—MVC
- java设计模式之模板设计模式和单例模式,以及复合
- Java 设计模式 -- 复合模式之一
- <Head First 设计模式>:复合模式:duck
- HeadFirst 设计模式 12复合模式
- 08@设计模式 - (06)复合模式
- 复合模式(Compound Pattern)之MVC模式
- java 开发模式之十四 : 复合模式
- IAR新建工程
- Swift_闭包
- POJ 1651 Multiplication Puzzle(区间DP 水题)
- Android内存分析实例(Eclipse+MAT)
- GRE写作必备句型
- 设计模式之复合模式
- day02--函数、数组、算法
- ShellExecute
- 2012年5月SAT香港真题解析
- Amr and The Large Array
- 我的学习之路
- oracle快速向表中插入记录方法
- snmp 设备测试方法
- Java强引用、 软引用、 弱引用、虚引用