组合模式:将对象组合成树形结构以表示‘部分-整体’的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。
透明方式:就是在component中声明所有用来管理子对象的方法,其中包括add,remove等,这样实现的Component接口的所有子类都具有add和remove,这样的好处是叶子节点和枝节点对于外界没有区别,他们具有完全一致的接口行为。但是问题也很突出,叶子节点不具有add和remove的功能,所以实现它也没有什么意义。
安全方式:Component接口中不去声明add和remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法,由于不够透明,所以叶子节点和枝节点将有不同的接口,客户端调用时需要做相应的判断,增加使用难度和不便。
应用实例: 1、算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作符也可以是操作数、操作符和另一个操作数。 2、在 JAVA AWT 和 SWING 中,对于 Button 和 Checkbox 是树叶,Container 是树枝。
实例UML图:
代码实现:
/**
* @author Shuyu.Wang
* @package:com.shuyu.composite
* @description:组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为,声明一个接口用于访问和管理Component的子部件
* @date 2018-11-28 13:27
**/
public abstract class Component {
protected String name;
public Component(String name){
this.name=name;
}
abstract void add(Component component);
abstract void remove(Component component);
abstract void display(int depth);
}
/**
* @author Shuyu.Wang
* @package:com.shuyu.composite
* @description:拼接字符串-
* @date 2018-11-28 13:58
**/
public class AppendString {
public static String appendChar(String chars,int depth){
if (depth<1){
return null;
}
StringBuffer stringBuffer=new StringBuffer();
for(int i=0;i<depth;i++){
stringBuffer.append(chars);
}
return stringBuffer.toString();
}
}
/**
* @author Shuyu.Wang
* @package:com.shuyu.composite
* @description:在组合中表示叶子节点对象,叶子节点没有子节点
* @date 2018-11-28 13:36
**/
@Slf4j
public class Leaf extends Component {
public Leaf(String name) {
super(name);
}
@Override
public void add(Component component) {
log.error("cannot add to a leaf");
}
@Override
public void remove(Component component) {
log.error("cannot remove to a leaf");
}
@Override
public void display(int depth) {
log.info(AppendString.appendChar("-",depth) + name);
}
}
/**
* @author Shuyu.Wang
* @package:com.shuyu.composite
* @description:定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,比如增加节点和移除节点
* @date 2018-11-28 13:40
**/
@Slf4j
public class Composite extends Component {
private List<Component> children = new ArrayList<Component>();
public Composite(String name) {
super(name);
}
@Override
public void add(Component component) {
children.add(component);
}
@Override
public void remove(Component component) {
children.remove(component);
}
@Override
public void display(int depth) {
log.info(AppendString.appendChar("-",depth)+ name);
for (Component c : children) {
c.display(depth + 2);
}
}
}
测试代码:
@RunWith(SpringRunner.class)
@SpringBootTest
public class CompositeApplicationTests {
@Test
public void contextLoads() {
Composite root=new Composite("root");
root.add(new Leaf("Leaf A"));
root.add(new Leaf("Leaf B"));
Composite comp=new Composite("Composite X");
comp.add(new Leaf("Leaf XA"));
comp.add(new Leaf("Leaf XB"));
root.add(comp);
Composite comp2=new Composite("Composite XY");
comp2.add(new Leaf("Leaf XYA"));
comp2.add(new Leaf("Leaf XYB"));
comp.add(comp2);
root.add(new Leaf("Leaf C"));
Leaf leaf=new Leaf("Leaf D");
root.add(leaf);
root.remove(leaf);
root.display(1);
}
}
执行结果:
2018-11-28 14:01:54.271 INFO 22368 --- [ main] com.shuyu.composite.Composite : -root
2018-11-28 14:01:54.272 INFO 22368 --- [ main] com.shuyu.composite.Leaf : ---Leaf A
2018-11-28 14:01:54.272 INFO 22368 --- [ main] com.shuyu.composite.Leaf : ---Leaf B
2018-11-28 14:01:54.272 INFO 22368 --- [ main] com.shuyu.composite.Composite : ---Composite X
2018-11-28 14:01:54.272 INFO 22368 --- [ main] com.shuyu.composite.Leaf : -----Leaf XA
2018-11-28 14:01:54.272 INFO 22368 --- [ main] com.shuyu.composite.Leaf : -----Leaf XB
2018-11-28 14:01:54.272 INFO 22368 --- [ main] com.shuyu.composite.Composite : -----Composite XY
2018-11-28 14:01:54.272 INFO 22368 --- [ main] com.shuyu.composite.Leaf : -------Leaf XYA
2018-11-28 14:01:54.272 INFO 22368 --- [ main] com.shuyu.composite.Leaf : -------Leaf XYB
2018-11-28 14:01:54.272 INFO 22368 --- [ main] com.shuyu.composite.Leaf : ---Leaf C
github代码地址:https://github.com/iot-wangshuyu/designpatterns/tree/master/composite