設計模式學習筆記(1)組合

本文實例代碼:github.com/JamesZBL/ja…java

組合(Composite)模式用於將對象組合成樹形結構以表示 「部分——總體」 的層次結構。它使得用戶對單個對象和組合對象的使用具備一致性。git

模式要點

組成部分

  • Component : 是組合中的全部對象的統一接口;定義了特定狀況下,類應當實現的貨缺省的行爲;Component 聲明一個接口用於訪問和管理 Component 的子組件;在遞歸結構中定義一個接口,用於訪問一個父部件,並符合條件的類中實現它,固然這個是可選的。
  • Leaf:在組合中表示葉節點對象,顧名思義,葉節點沒有子節點。
  • Composite:定義有子部件的那些部件的行爲,同時存儲子部件,實現 Component 中與子部件有關的接口。
  • Client:經過Component接口,操縱組合部件的對象。

協做原理

  • 用戶使用Component類接口與組合結構中的對象進行交互。 若是接收者是一個葉節點,則直接處理請求。 若是接收者是Composite, 它一般將請求發送給它的子部件, 在轉發請求以前與/或以後可能執行一些輔助操做。

實例分析

在中文中,一句話是由詞語組成的,而詞語又由字組成;在英文中,句子由單詞組成,而單詞又由一個個字母組成。每一個對象均可定義的它以前的或以後的內容。好比一箇中文句子老是以句號結尾,一個英文單詞以前一般是有空格的。這種結構能夠造成了遞歸嵌套的結構,句子是父容器,單詞是子容器,字母是葉節點。 github

CharacterComposite 是一個抽象類,定義了全部容器類或葉節點的接口,容器應當實現的功能有:獲取子組件、對子組件進行計數、定義組件的格式化輸出規則。Sentence(句子) 和 Word (單詞)都屬於容器,而 Character (字母)則屬於葉節點,由於字母中沒法再添加子組件了,它是層次結構中的最末端。

/** * 全部容器的抽象父類 */
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 組件後應當輸出一個「。」等。ide

/** * 英文句子 */
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 的子組件,屬於葉節點。this

/** * 字母 */
public class Character extends CharacterComposite {

  private char c;

  public Character(char c) {
    this.c = c;
  }

  @Override
  public void print() {
    System.out.print(c);
  }
}
複製代碼

Writer 爲句子生成器,各個組件及子組件均由它負責填充,最終造成一個完成的結構。spa

/** * 語句生成器 */
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);
  }
}
複製代碼

效果

  • Composite 模式定義了基本對象和組合對象的基本層次結構,基本對象能夠組合造成更復雜的對象,這個對象還能夠再次進行組合,依次類推,能夠實現無限層的遞歸嵌套結構,上文中提到的句子-單詞-字母結構便是如此。
  • 全部的容器都是這個接口的實現,用戶能夠一致地使用組合結構和單個對象,用戶不須要知道它是否爲葉節點或包含子容器的一個組件,從而大大簡化了代碼結構,定義組合的類時避免了各類複雜的包含着大量判斷的方法。
  • 在增長新的組件的時候更簡單,不管是新增一種容器或一個葉節點都很方便,無需單獨再定義新類而且能夠很容易和現有的組件或容器結合工做,客戶端無需隨新組件的增長而作任何改變
  • 使代碼結構更具通用性,但也存在一些問題。增長組件很方便,但沒法對子組件作過多的限制,即便客戶但願在容器中只增長某種特定的組件,因爲使用 Composite 而沒法依靠別的類作過多的約束,這些檢驗類型的工做就要放到運行時去作了

適用場景

  • 你想表示對象的部分-總體層次結構
  • 你但願用戶忽略組合對象與單個對象的不一樣, 用戶將統一地使用組合結構中的全部對象

我的博客同步更新,獲取更多技術分享請關注:鄭保樂的博客3d

相關文章
相關標籤/搜索