
组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得客户端对单个对象和复合对象的使用具有一致性。在实际项目中,组合模式常用于构建复杂的嵌套结构,如文件目录、组织结构等。
组合模式包含以下角色:
在Java中实现组合模式时,通常有两种主要的方法:透明组合模式和安全组合模式。这两种实现方式在处理子组件的管理上有所不同。
透明组合模式中,抽象组件(Component)会声明所有用于管理子组件的方法,如添加(add)、移除(remove)和获取子组件(getChild)等。因此,对于客户端来说,无论是叶子节点还是复合节点,它们都具备相同的接口。但是,叶子节点中的这些方法可能没有任何实际操作,甚至抛出异常。
// 透明组合模式的抽象组件
interface Component {
void operation();
void add(Component component);
void remove(Component component);
Component getChild(int index);
}
// 叶子组件
class Leaf implements Component {
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void operation() {
// 实现具体操作
}
@Override
public void add(Component component) {
// 对于叶子节点,这个方法可能没有意义
throw new UnsupportedOperationException("Cannot add children to leaf nodes.");
}
@Override
public void remove(Component component) {
// 对于叶子节点,这个方法可能没有意义
throw new UnsupportedOperationException("Cannot remove children from leaf nodes.");
}
@Override
public Component getChild(int index) {
// 对于叶子节点,这个方法可能没有意义
return null;
}
}
// 复合组件
class Composite implements Component {
private List<Component> children = new ArrayList<>();
@Override
public void operation() {
// 实现具体操作,并且可能会递归调用子组件的操作
}
@Override
public void add(Component component) {
children.add(component);
}
@Override
public void remove(Component component) {
children.remove(component);
}
@Override
public Component getChild(int index) {
return children.get(index);
}
}在透明组合模式中,由于客户端可以调用叶子节点上的add()和remove()方法(尽管这样做会导致异常),所以这种方式被认为不是类型安全的。
安全组合模式中,抽象组件只声明了共同的方法(通常是业务方法),不声明管理子组件的方法。这些方法被单独定义在复合组件中。这样,叶子节点就不会拥有这些不相关的方法,客户端在使用时也无法调用这些方法,因此是类型安全的。
// 安全组合模式的抽象组件
interface Component {
void operation();
}
// 叶子组件
class Leaf implements Component {
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void operation() {
// 实现叶子节点的具体操作
}
}
// 复合组件
class Composite implements Component {
private List<Component> children = new ArrayList<>();
@Override
public void operation() {
// 实现复合组件的具体操作,可能包含对子组件的调用
for (Component child : children) {
child.operation();
}
}
public void add(Component component) {
children.add(component);
}
public void remove(Component component) {
children.remove(component);
}
public Component getChild(int index) {
return children.get(index);
}
}在安全组合模式中,由于管理子组件的方法仅在Composite类中定义,所以客户端不能直接调用这些方法(除非它有一个指向Composite对象的引用),因此是类型安全的。这种方式避免了客户端调用叶子节点上的不存在的方法时可能出现的运行时错误。在实际开发中,安全组合模式更为常见。
在实际项目中,不妨尝试运用组合模式来解决类似文件目录、组织结构等场景的问题。
术因分享而日新,每获新知,喜溢心扉。 诚邀关注公众号 『
码到三十五』 ,获取更多技术资料。