java设计模式(结构)--组合模式&装饰器模式

一、组合模式

用途:将对象组合成树形结构以表示 “部分——整体” 的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。

案例:在中文中,一句话是由词语组成的,而词语又由字组成;在英文中,句子由单词组成,而单词又由一个个字母组成。每个对象都可定义的它之前的或之后的内容。比如一个中文句子总是以句号结尾,一个英文单词之前通常是有空格的。这种结构可以形成了递归嵌套的结构,句子是父容器,单词是子容器,字母是叶节点。 

/**
 * 所有容器的抽象父类
 */
public abstract class CharacterComposite {

  private List<CharacterComposite> 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<EnglishWord> words) {
    for (EnglishWord word : words) {
      add(word);
    }
  }

  @Override
  public void printAfter() {
    System.out.println(".");
  }
}
/**
 * 英文单词
 */
public class EnglishWord extends CharacterComposite {

  public EnglishWord(List<Character> 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<ChineseWord> 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<EnglishWord> 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();
  }
}

输出如下内容

仅由木匠制作锤把
    检查木材
    打造锤把
    检查成品锤把
    
    由铁匠完成锤把以及锤头的制作
    检查木材
    检查铁材
    打造锤把
    打造锤头
    检查成品锤把
    检查成品锤头

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值