用途:将对象组合成树形结构以表示 “部分——整体” 的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
案例:在中文中,一句话是由词语组成的,而词语又由字组成;在英文中,句子由单词组成,而单词又由一个个字母组成。每个对象都可定义的它之前的或之后的内容。比如一个中文句子总是以句号结尾,一个英文单词之前通常是有空格的。这种结构可以形成了递归嵌套的结构,句子是父容器,单词是子容器,字母是叶节点。
/**
* 所有容器的抽象父类
*/
public abstract class CharacterComposite {
private List children = new ArrayList<>();
public void add(CharacterComposite character) {
children.add(character);
}
public int count() {
return this.children.size();
}
public void printBefore() {
}
public void printAfter() {
}
public void print() {
printBefore();
for (CharacterComposite item : children) {
item.print();
}
printAfter();
}
}
EnglishWord 组件前应当输出一个空格,EnglishSentence 组件后应当输出一个“.”,ChineseSentence 组件后应当输出一个“。”等
/**
* 英文句子
*/
public class EnglishSentence extends CharacterComposite {
public EnglishSentence(List words) {
for (EnglishWord word : words) {
add(word);
}
}
@Override
public void printAfter() {
System.out.println(".");
}
}
/**
* 英文单词
*/
public class EnglishWord extends CharacterComposite {
public EnglishWord(List characters) {
for (Character c : characters) {
add(c);
}
}
@Override
public void printBefore() {
System.out.print(" ");
}
}
Word 作为 Sentence 的子容器,Character 作为 Word 的子组件,属于叶节点。
/**
* 字母
*/
public class Character extends CharacterComposite {
private char c;
public Character(char c) {
this.c = c;
}
@Override
public void print() {
System.out.print(c);
}
}
Writer 为句子生成器,各个组件及子组件均由它负责填充,最终形成一个完成的结构。
/**
* 语句生成器
*/
public class Writer {
public CharacterComposite sentenceByChinese() {
List words = new ArrayList<>();
words.add(new ChineseWord(Arrays.asList(new Character('我'))));
words.add(new ChineseWord(Arrays.asList(new Character('是'))));
words.add(new ChineseWord(Arrays.asList(new Character('来'), new Character('自'))));
words.add(new ChineseWord(Arrays.asList(new Character('北'), new Character('京'))));
words.add(new ChineseWord(Arrays.asList(new Character('的'))));
words.add(new ChineseWord(Arrays.asList(new Character('小'), new Character('明'))));
return new ChineseSentence(words);
}
public CharacterComposite sentenceByEnglish() {
List words = new ArrayList<>();
words.add(new EnglishWord(Arrays.asList(new Character('I'))));
words.add(new EnglishWord(Arrays.asList(new Character('a'), new Character('m'))));
words.add(new EnglishWord(Arrays.asList(new Character('a'))));
words.add(new EnglishWord(Arrays.asList(new Character('s'), new Character('t'), new Character('u'), new Character('d'), new Character('e'), new Character('n'), new Character('t'))));
words.add(new EnglishWord(Arrays.asList(new Character('f'), new Character('r'), new Character('o'), new Character('m'))));
words.add(new EnglishWord(Arrays.asList(new Character('L'), new Character('o'), new Character('n'), new Character('d'), new Character('o'), new Character('n'))));
return new EnglishSentence(words);
}
}
用途:用于动态地给一个对象添加一些额外的职责。 就增加功能来说, Decorator模式相比生成子类更为灵活。装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
案例:铁匠和木匠同时制作一把铁锤,第一种方案是木匠制作锤把,铁匠制作锤头;第二中方案是铁匠先制作锤把再制作锤头(假定这里的木匠只会制作锤把)。制作过程分为三部分:1.对材料进行初步的检查,2.进行制造并把部件安装起来以供后面的操作,3.完成之后再次进行检查,确保没有质量问题。
首先定义“操作”接口,包括前后两次检查以及安装的操作。
/**
* 流水线上操作行为的接口
*/
public interface Operation {
void checkBefore();
void join();
void chekcAfter();
}
现在只由木匠制作锤把,定义一个木匠的操作类 CarpenterOperation
/**
* 木匠的工作
*/
public class CarpenterOperation implements Operation {
private static final Logger LOGGER = LoggerFactory.getLogger(CarpenterOperation.class);
@Override
public void checkBefore() {
LOGGER.info("检查木材");
}
@Override
public void join() {
LOGGER.info("打造锤把");
}
@Override
public void chekcAfter() {
LOGGER.info("检查成品锤把");
}
}
由于某些原因,铁匠决定自己制作锤把,现在铁匠身兼双职,将木匠的工作也承担了。定义一个铁匠操作类 HammerSmith
/**
* 铁匠
*/
public class HammerSmithOperation implements Operation {
private static final Logger LOGGER = LoggerFactory.getLogger(HammerSmithOperation.class);
private Operation previousOperation;
public HammerSmithOperation(Operation previousOperation) {
this.previousOperation = previousOperation;
}
@Override
public void checkBefore() {
previousOperation.checkBefore();
LOGGER.info("检查铁材");
}
@Override
public void join() {
previousOperation.join();
LOGGER.info("打造锤头");
}
@Override
public void chekcAfter() {
previousOperation.chekcAfter();
LOGGER.info("检查成品锤头");
}
}
同样实现了“操作”的接口,铁匠的每个操作都包含了木匠相应的操作,相当于对木匠的操作增加了一层包裹和扩展。这种包装就是 Decorator 模式中的装饰。
现在分别让木匠和铁匠进行一系列操作
/**
* Decorator
*/
public class me.zbl.ovserver.Application {
private static final Logger LOGGER = LoggerFactory.getLogger(me.zbl.ovserver.Application.class);
public static void main(String[] args) {
LOGGER.info("仅由木匠制作锤把");
Operation carpenter = new CarpenterOperation();
carpenter.checkBefore();
carpenter.join();
carpenter.chekcAfter();
LOGGER.info("由铁匠完成锤把以及锤头的制作");
Operation hammerSmith = new HammerSmithOperation(carpenter);
hammerSmith.checkBefore();
hammerSmith.join();
hammerSmith.chekcAfter();
}
}
输出如下内容
仅由木匠制作锤把
检查木材
打造锤把
检查成品锤把
由铁匠完成锤把以及锤头的制作
检查木材
检查铁材
打造锤把
打造锤头
检查成品锤把
检查成品锤头