* add state and callback pattern * add command and template-method pattern * add iterator pattern * add bridege and DI pattern * fix issue #1600 * add converter,proxy,visitor pattern * add caching,composite,delegation,dirty-flag,interpreter patterns * add dao and producer-consumer * add dto and provate class data pattern * fix #1646 png path problems * fix #1646 composite png path case problem Co-authored-by: Mike <admin@xiaod.info> Co-authored-by: Subhrodip Mohanta <hello@subho.xyz>
175 lines
4.9 KiB
Markdown
175 lines
4.9 KiB
Markdown
---
|
||
layout: pattern
|
||
title: Composite
|
||
folder: composite
|
||
permalink: /patterns/composite/
|
||
categories: Structural
|
||
tags:
|
||
- Gang of Four
|
||
---
|
||
|
||
## 目的
|
||
|
||
将对象组合成树结构以表示部分整体层次结构。 组合可以使客户统一对待单个对象和组合对象。
|
||
|
||
## 解释
|
||
|
||
真实世界例子
|
||
|
||
> 每个句子由单词组成,单词又由字符组成。这些对象中的每一个都是可打印的,它们可以在它们之前或之后打印一些内容,例如句子始终以句号结尾,单词始终在其前面有空格。
|
||
|
||
通俗的说
|
||
|
||
> 组合模式使客户能够以统一的方式对待各个对象。
|
||
|
||
维基百科说
|
||
|
||
> 在软件工程中,组合模式是一种分区设计模式。组合模式中,一组对象将像一个对象的单独实例一样被对待。组合的目的是将对象“组成”树状结构,以表示部分整体层次结构。实现组合模式可使客户统一对待单个对象和组合对象。
|
||
|
||
**程序示例**
|
||
|
||
使用上面的句子例子。 这里我们有基类`LetterComposite`和不同的可打印类型`Letter`,`Word`和`Sentence`。
|
||
|
||
```java
|
||
public abstract class LetterComposite {
|
||
|
||
private final List<LetterComposite> 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();
|
||
children.forEach(LetterComposite::print);
|
||
printThisAfter();
|
||
}
|
||
}
|
||
|
||
public class Letter extends LetterComposite {
|
||
|
||
private final char character;
|
||
|
||
public Letter(char c) {
|
||
this.character = c;
|
||
}
|
||
|
||
@Override
|
||
protected void printThisBefore() {
|
||
System.out.print(character);
|
||
}
|
||
}
|
||
|
||
public class Word extends LetterComposite {
|
||
|
||
public Word(List<Letter> letters) {
|
||
letters.forEach(this::add);
|
||
}
|
||
|
||
public Word(char... letters) {
|
||
for (char letter : letters) {
|
||
this.add(new Letter(letter));
|
||
}
|
||
}
|
||
|
||
@Override
|
||
protected void printThisBefore() {
|
||
System.out.print(" ");
|
||
}
|
||
}
|
||
|
||
public class Sentence extends LetterComposite {
|
||
|
||
public Sentence(List<Word> words) {
|
||
words.forEach(this::add);
|
||
}
|
||
|
||
@Override
|
||
protected void printThisAfter() {
|
||
System.out.print(".");
|
||
}
|
||
}
|
||
```
|
||
|
||
然后我们有一个消息携带者来携带消息。
|
||
|
||
```java
|
||
public class Messenger {
|
||
|
||
LetterComposite messageFromOrcs() {
|
||
|
||
var words = List.of(
|
||
new Word('W', 'h', 'e', 'r', 'e'),
|
||
new Word('t', 'h', 'e', 'r', 'e'),
|
||
new Word('i', 's'),
|
||
new Word('a'),
|
||
new Word('w', 'h', 'i', 'p'),
|
||
new Word('t', 'h', 'e', 'r', 'e'),
|
||
new Word('i', 's'),
|
||
new Word('a'),
|
||
new Word('w', 'a', 'y')
|
||
);
|
||
|
||
return new Sentence(words);
|
||
|
||
}
|
||
|
||
LetterComposite messageFromElves() {
|
||
|
||
var words = List.of(
|
||
new Word('M', 'u', 'c', 'h'),
|
||
new Word('w', 'i', 'n', 'd'),
|
||
new Word('p', 'o', 'u', 'r', 's'),
|
||
new Word('f', 'r', 'o', 'm'),
|
||
new Word('y', 'o', 'u', 'r'),
|
||
new Word('m', 'o', 'u', 't', 'h')
|
||
);
|
||
|
||
return new Sentence(words);
|
||
|
||
}
|
||
|
||
}
|
||
```
|
||
|
||
然后它可以这样使用:
|
||
|
||
```java
|
||
var orcMessage = new Messenger().messageFromOrcs();
|
||
orcMessage.print(); // Where there is a whip there is a way.
|
||
var elfMessage = new Messenger().messageFromElves();
|
||
elfMessage.print(); // Much wind pours from your mouth.
|
||
```
|
||
|
||
## 类图
|
||
|
||

|
||
|
||
## 适用性
|
||
|
||
使用组合模式当
|
||
|
||
* 你想要表示对象的整体层次结构
|
||
* 你希望客户能够忽略组合对象和单个对象之间的差异。 客户将统一对待组合结构中的所有对象。
|
||
|
||
## 真实世界例子
|
||
|
||
* [java.awt.Container](http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html) and [java.awt.Component](http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html)
|
||
* [Apache Wicket](https://github.com/apache/wicket) component tree, see [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java) and [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)
|
||
|
||
## 鸣谢
|
||
|
||
* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)
|
||
* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)
|
||
* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)
|