合成模式
合成(Composite)模式属于对象的结构模式。
1.定义:合成模式将对象组织到树结构中,可以用来描述整体和部分的关系。合成模式可以使客户端将单纯的元素和复合的元素同等看待。
注意:就如阎博士书中所说,用文件系统来理解合成模式是个很好的方式。
2.两种实现
1)透明式:子结点集合的管理方法在抽象类或接口中定义,向客户端隐藏树叶结点和树枝结点的区别。
缺点:虽然树枝对象还是树叶对象在客户端看来是没区别了,但是他们两者确实是有区别的。使用透明式的实现方式,就会发生这样的情况:客户端可能调用了树叶对象的子结点管理方法,使用透明式实现使得这样的错误在编译器无法被检查出来,只能延迟到运行期才会暴露出来。(说白了就是客户端可能会调到空的方法。)
2)安全式:子结点集合的管理方式只在树枝接点中定义,客户端必须明确知道当前对象到底是树枝还是树叶。
缺点:这种方式不够透明,树枝和树叶具有不同的接口,客户端就不能把它们当成同一类对象看待了。(说白了就是不能把树枝和树叶全部上转成他们的抽象类或接口。)
3.合成模式实现的几个问题
1)树的方向(说白了就是:子结点中是否应该维持父结点的引用,父结点中是否应该维持子结点的引用)
2)遍历时缓存(不明白撒意思)
3)客户端不应该直接调用树叶类,应当由父类向树叶类进行委派。(不明白撒意思)
4.应该使用合成模式的情形
1)需要描述对象的部分和整体的等级结构
2)需要客户端忽略掉个体构件和组合构件的区别。客户端必须平等对待所有的构件,包括个体构件和组合构件
5.合成模式的优点
1)合成模式可以很容易地增加新种类的构件
2)使用合成模式可以使得构件对客户端透明
6.合成模式的缺点
1)不容易控制树枝构件的类型
2)使用继承的方法来增加新的行为比较困难。
7.思考
前段时间碰到的权限管理,里面就有权限树的概念,可否应用合成模式?
实例:文件系统
import java.util.*;
public abstract class FileSystemComponent {
String name;
public FileSystemComponent(String cName) {
name = cName;
}
public void addComponent(FileSystemComponent component)
throws CompositeException {
throw new CompositeException(
"Invalid Operation. Not Supported");
}
public FileSystemComponent getComponent(int componentNum)
throws CompositeException {
throw new CompositeException(
"Invalid Operation. Not Supported");
}
public abstract long getComponentSize();
} // End of class FileSystemComponent
import java.util.*;
public class FileComponent extends FileSystemComponent {
private long size;
public FileComponent(String cName, long sz) {
super(cName);
size = sz;
}
public long getComponentSize() {
return size;
}
} // End of class
import java.util.*;
public class DirComponent extends FileSystemComponent {
Vector dirContents = new Vector();
//individual files/sub folders collection
public DirComponent(String cName) {
super(cName);
}
public void addComponent(FileSystemComponent fc)
throws CompositeException {
dirContents.add(fc);
}
public FileSystemComponent getComponent(int location)
throws CompositeException {
return (FileSystemComponent) dirContents.elementAt(
location);
}
public long getComponentSize() {
long sizeOfAllFiles = 0;
Enumeration e = dirContents.elements();
while (e.hasMoreElements()) {
FileSystemComponent component =
(FileSystemComponent) e.nextElement();
sizeOfAllFiles = sizeOfAllFiles +
(component.getComponentSize());
}
return sizeOfAllFiles;
}
} // End of class
文档与源代码下载地址:http://download.csdn.net/detail/hnzhangshilong/3685894