前言:
最近在看设计模式,首先推荐个不错的与设计模式相关的github项目:
java-design-patterns:java设计模式很详细内容也很充实的开源项目
wiki地址:
Composite Pattern
介绍:
之前的误解一直认为Composite就是和继承相对应的组合的扩展类的方式。最近在翻看相关内容的是否才发现自己是理解岔了。
Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.
组合模式主要解决的是树结构的问题,能够将整体或个体同等对待。
上面的意思是当什么问题能够转换为树状结构,我们就要考虑是否能够利用组合模式来进行解决。
wiki的解释:
In software engineering, the composite pattern is a partitioning design pattern. The composite pattern describes that a group of objects is to be treated in the same way as a single instance of an object. The intent of a composite is to "compose" objects into tree structures to represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual objects and compositions uniformly.
也是大同小异。我们以树结构来进行理解,整个树或者任意子树,既可以用它所对应的根节点来表示,而具体的每个节点(叶子节点,根节点,分支等)也是个节点类型,所以这就是上面所说的对于个体和整体能够同等对待的意思。
UML图
这个UML图最能体现出组合设计模式的核心思想。Leaf和Composite均继承自Component组件,而Composite中又包含了组件(多以List的形式)。
例子:
该例子选自前言中项目中的例子,地址:http://java-design-patterns.com/patterns/composite/
// 最关键的一步,自己包含自己的一个List,Composite包含一个List的属性
public abstract class LetterComposite {
private List children = new ArrayList<>();
public void add(LetterComposite letter) {
children.add(letter);
}
public int count() {
return children.size();
}
protected void printThisBefore() {}
protected void printThisAfter() {}
public void print() {
printThisBefore();
for (LetterComposite letter : children) {
letter.print();
}
printThisAfter();
}
}
// 所有的对象只要扩展自LetterComposite即可
public class Letter extends LetterComposite {
private char c;
public Letter(char c) {
this.c = c;
}
@Override
protected void printThisBefore() {
System.out.print(c);
}
}
// 所有的对象只要扩展自LetterComposite即可
public class Word extends LetterComposite {
public Word(List letters) {
for (Letter l : letters) {
this.add(l);
}
}
@Override
protected void printThisBefore() {
System.out.print(" ");
}
}
// 所有的对象只要扩展自LetterComposite即可
public class Sentence extends LetterComposite {
public Sentence(List words) {
for (Word w : words) {
this.add(w);
}
}
@Override
protected void printThisAfter() {
System.out.print(".");
}
}
组装:
public class Messenger {
LetterComposite messageFromOrcs() {
List words = new ArrayList<>();
words.add(new Word(Arrays.asList(new Letter('W'), new Letter('h'), new Letter('e'), new Letter('r'), new Letter('e'))));
words.add(new Word(Arrays.asList(new Letter('t'), new Letter('h'), new Letter('e'), new Letter('r'), new Letter('e'))));
words.add(new Word(Arrays.asList(new Letter('i'), new Letter('s'))));
words.add(new Word(Arrays.asList(new Letter('a'))));
words.add(new Word(Arrays.asList(new Letter('w'), new Letter('h'), new Letter('i'), new Letter('p'))));
words.add(new Word(Arrays.asList(new Letter('t'), new Letter('h'), new Letter('e'), new Letter('r'), new Letter('e'))));
words.add(new Word(Arrays.asList(new Letter('i'), new Letter('s'))));
words.add(new Word(Arrays.asList(new Letter('a'))));
words.add(new Word(Arrays.asList(new Letter('w'), new Letter('a'), new Letter('y'))));
return new Sentence(words);
}
LetterComposite messageFromElves() {
List words = new ArrayList<>();
words.add(new Word(Arrays.asList(new Letter('M'), new Letter('u'), new Letter('c'), new Letter('h'))));
words.add(new Word(Arrays.asList(new Letter('w'), new Letter('i'), new Letter('n'), new Letter('d'))));
words.add(new Word(Arrays.asList(new Letter('p'), new Letter('o'), new Letter('u'), new Letter('r'), new Letter('s'))));
words.add(new Word(Arrays.asList(new Letter('f'), new Letter('r'), new Letter('o'), new Letter('m'))));
words.add(new Word(Arrays.asList(new Letter('y'), new Letter('o'), new Letter('u'), new Letter('r'))));
words.add(new Word(Arrays.asList(new Letter('m'), new Letter('o'), new Letter('u'), new Letter('t'), new Letter('h'))));
return new Sentence(words);
}
}
对于组合模式来讲,我们虽然将整体和个体进行了同等的对待,但是组装却是难免的。而如何更加灵活的进行组装,便有不同的选择方式,比如通过xml来进行配置,或者通过数据库配置亦可。
总结:
对于Composite组合设计模式来讲,解决的问题是对于类树的结构,如何将整体和个体进行统一对待,而由于统一的进行了对待,所以和递归的想法又有了契合。