Index
複数のオブジェクトを鎖のように繋いでおき、そのオブジェクトの鎖を順次渡り歩いて、目的のオブジェクトを決定するデザインパターン
ざっくりいうと、目的の処理をしてくれるオブジェクトまでたらい回しにするパターンのことです。
サンプルコードを見ながら、理解を深めていきましょう!
- 要求する側と処理をする側の結びつきを弱めることができる
- 動的にたらい回しの順番を変えることができる
- 自分の仕事に集中できる
- 処理が遅くなる
誰が要求を処理すべきか前もって決まっていて、その相手がすぐに処理をする場合に比べると処理が遅くなってしまいます。
サンプルコードとして、役所に書類を提出するときに担当の課にたどり着くまでたらい回しされるようなコードを作ってみました。
クラス図は以下のようになっております。
提出する書類を表すクラスです。
m_numberは書類の種類を表しています。
後述する課クラスはこのm_numberを見て書類を処理するか判断します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class Document { private final int m_number;//書類の種類 public Document(final int number) { this.m_number = number; } public int getNumber() { return m_number; } @Override public String toString() { return String.format("[Document %d ]", m_number); } } |
このクラスは各課の抽象クラスとなります。
m_nextフィールドはたらい回しする先を示しています。
supportメソッドはTemplate Methodパターンを使用しています。
TemplateMethodパターン@Java言語で学ぶデザインパターン入門
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
public abstract class Support { private final String m_name;//窓口担当者の名前 private Support m_next; public Support(final String name) { m_name = name; m_next = null; } public Support setNext(final Support next) { m_next = next; return next; } //たらい回し先を設定する public void support(final Document document) { if(resolve(document)) { done(document); } else if(m_next != null) { m_next.support(document); } else { fail(document); } } //ドキュメント解決者の文字列表現 @Override public String toString() { return "[" + m_name + "]"; } //解決しようとする protected abstract boolean resolve(final Document document); //解決した protected void done(final Document document) { System.out.println(document + "is resolved by " + this + "."); } //解決しなかった protected void fail(final Document document) { System.out.println(document + "cannot be resolved"); } } |
住民課を表したクラスです。
書類番号9以下の書類を処理してくれます。
自分の範囲外のことは知らずに実装できているのが特徴です(自分の仕事に集中できるメリット)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class Juminka extends Support{ public Juminka(final String name) { super(name); } //書類番号が10未満の書類を処理する @Override protected boolean resolve(final Document document) { return document.getNumber() < 10; } } |
マイナンバー課クラス。
自分の範囲外のことは知らずに実装できているのが特徴です(自分の仕事に集中できるメリット)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class MyNumberka extends Support{ public MyNumberka(String name) { super(name); } @Override protected boolean resolve(Document document) { //書類番号が10以上20未満の書類を処理する return document.getNumber() >= 10 && document.getNumber() < 20; } } |
福祉課クラス
自分の範囲外のことは知らずに実装できているのが特徴です(自分の仕事に集中できるメリット)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class Fukusika extends Support{ public Fukusika(String name) { super(name); } @Override protected boolean resolve(Document document) { //書類番号が20以上30未満の書類を処理する return document.getNumber() >= 20 && document.getNumber() < 30; } } |
まず各課の担当者を作成します。
次にsetNextメソッドを使ってたらい回しする順番をセットします。(動的にたらい回しの順番を変えることができるメリット)
あとは適当に書類を作って担当の者に処理させています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class Main { public static void main(String[] args) { final Support tanaka = new Juminka("Tanaka"); final Support yoshida = new Fukusika("Yoshida"); final Support sato = new MyNumberka("Sato"); //連鎖の形成 tanaka.setNext(yoshida).setNext(yoshida).setNext(sato); //書類の処理 for (int i = 0 ; i < 100; i += 10) { tanaka.support(new Document(i)); } } } |
1 2 3 4 5 6 7 8 9 10 |
[Document 0 ]is resolved by [Tanaka]. [Document 10 ]is resolved by [Sato]. [Document 20 ]is resolved by [Yoshida]. [Document 30 ]cannot be resolved [Document 40 ]cannot be resolved [Document 50 ]cannot be resolved [Document 60 ]cannot be resolved [Document 70 ]cannot be resolved [Document 80 ]cannot be resolved [Document 90 ]cannot be resolved |
Compositeパターン@Java言語によるデザインパターン入門
java言語で学ぶデザインパターン入門第3版を参考にさせていただきました!