组合模式的定义
将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式的本质
统一叶子对象和组合对象。
示例1
如果想要安全性,就把父类中在Leaf中没有的方法去掉。
想要透明性,就加上。
/**
* 抽象的组件对象,为组合中的对象声明接口,实现接口的缺省行为
*/
public abstract class Component {
/**输出组件自身的名称*/
public abstract void printStruct(String preStr);
/**加入组件对象*/
public void addChild(Component child) {
throw new UnsupportedOperationException("对象不支持这个功能");
}
/**删除组件对象*/
public void removeChild(Component child) {
throw new UnsupportedOperationException("对象不支持这个功能");
}
/**返回组件对象*/
public Component getChildren(int index) {
throw new UnsupportedOperationException("对象不支持这个功能");
}
}
import java.util.ArrayList;
import java.util.List;
/**
* 组合对象,可以包含其他组合对象或者叶子对象
*/
public class Composite extends Component{
/**用来存储组合对象中的子组件*/
private List<Component> childComponents = null;
/**组合对象的名字*/
private String name = "";
public Composite(String name) {
this.name = name;
}
@Override
public void addChild(Component child) {
//延迟初始化
if (null == childComponents ) {
childComponents = new ArrayList<>();
}
childComponents.add(child);
}
@Override
public void printStruct(String preStr) {
//先把自己输出去
System.out.println(preStr+"+"+this.name);
//如果还包含子组件,那么就输出这些子组件对象
if (null != this.childComponents) {
//添加一个空格,表示向后缩进一个空格
preStr += " ";
for (Component c: childComponents) {
c.printStruct(preStr);
}
}
}
}
**
* 叶子对象
*/
public class Leaf extends Component {
/**叶子对象的名字*/
private String name = "";
public Leaf(String name) {
this.name = name;
}
/**
* 输出叶子对象的结果,叶子对象没有子对象,也就是输出叶子对象的名字
* @param preStr
*/
@Override
public void printStruct(String preStr) {
System.out.println(preStr+"-"+name);
}
}
public class TestClient {
public static void main(String[] args) {
Composite root = new Composite("服装");
Composite c1 = new Composite("男装");
Composite c2 = new Composite("女装");
Leaf leaf1 = new Leaf("衬衣");
Leaf leaf2 = new Leaf("夹克");
Leaf leaf3 = new Leaf("裙子");
Leaf leaf4 = new Leaf("套装");
root.addChild(c1);
root.addChild(c2);
c1.addChild(leaf1);
c1.addChild(leaf2);
c2.addChild(leaf3);
c2.addChild(leaf4);
root.printStruct("");
}
}
示例2
import java.util.List;
/**
* 抽象的组件对象,为组合中的对象声明接口,实现接口的缺省行为
*/
public abstract class Component {
/**记录父组件对象*/
private Component parent = null;
public Component getParent() {
return parent;
}
public void setParent(Component parent) {
this.parent = parent;
}
/**返回某个对象的子组件对象*/
public List<Component> getChildren() {
throw new UnsupportedOperationException("对象不支持这个功能");
}
/**输出组件自身的名称*/
public abstract void printStruct(String preStr);
/**加入组件对象*/
public void addChild(Component child) {
throw new UnsupportedOperationException("对象不支持这个功能");
}
/**删除组件对象*/
public void removeChild(Component child) {
throw new UnsupportedOperationException("对象不支持这个功能");
}
/**返回组件对象*/
public Component getChildren(int index) {
throw new UnsupportedOperationException("对象不支持这个功能");
}
}
import java.util.ArrayList;
import java.util.List;
/**
* 组合对象,可以包含其他组合对象或者叶子对象
*/
public class Composite extends Component{
/**用来存储组合对象中的子组件*/
private List<Component> childComponents = null;
/**组合对象的名字*/
private String name = "";
public Composite(String name) {
this.name = name;
}
@Override
public void addChild(Component child) {
//添加对父组件的引用
child.setParent(this);
//延迟初始化
if (null == childComponents ) {
childComponents = new ArrayList<>();
}
childComponents.add(child);
}
@Override
public void removeChild(Component child) {
if (null != this.childComponents) {
//查找要删除的组件在集合中的索引位置
int idx = childComponents.indexOf(child);
if (-1 != idx) {
//把要删除的组件的子组件的父组件设置为本类的,然后添加进集合
for (Component c:child.getChildren()) {
c.setParent(this);
childComponents.add(c);
}
}
childComponents.remove(idx);
}
}
@Override
public List<Component> getChildren() {
return childComponents;
}
@Override
public void printStruct(String preStr) {
//先把自己输出去
System.out.println(preStr+"+"+this.name);
//如果还包含子组件,那么就输出这些子组件对象
if (null != this.childComponents) {
//添加一个空格,表示向后缩进一个空格
preStr += " ";
for (Component c: childComponents) {
c.printStruct(preStr);
}
}
}
}
/**
* 叶子对象
*/
public class Leaf extends Component {
/**叶子对象的名字*/
private String name = "";
public Leaf(String name) {
this.name = name;
}
/**
* 输出叶子对象的结果,叶子对象没有子对象,也就是输出叶子对象的名字
* @param preStr
*/
@Override
public void printStruct(String preStr) {
System.out.println(preStr+"-"+name);
}
}
public class TestClient {
public static void main(String[] args) {
Composite root = new Composite("服装");
Composite c1 = new Composite("男装");
Composite c2 = new Composite("女装");
Leaf leaf1 = new Leaf("衬衣");
Leaf leaf2 = new Leaf("夹克");
Leaf leaf3 = new Leaf("裙子");
Leaf leaf4 = new Leaf("套装");
root.addChild(c1);
root.addChild(c2);
c1.addChild(leaf1);
c1.addChild(leaf2);
c2.addChild(leaf3);
c2.addChild(leaf4);
root.printStruct("");
System.out.println("-------------------------");
root.removeChild(c1);
root.printStruct("");
}
}