Skip to content

Instantly share code, notes, and snippets.

@tamanishi
Last active May 6, 2019 02:18
Show Gist options
  • Save tamanishi/a4dda78fbd65114dd0762040e65c847b to your computer and use it in GitHub Desktop.
Save tamanishi/a4dda78fbd65114dd0762040e65c847b to your computer and use it in GitHub Desktop.

Java言語で学ぶデザインパターン入門を読んだメモ

Iterator

  • 集合の実装と数え上げのインタフェーフェースを分離

Adapter

Template Method

Factory Method

  • インスタンス生成の手続きを規定
  • 手続き一つ一つの実装はサブクラスで決める

Singleton

  • getInstance で if (instance == null) new する実装は
    マルチスレッドで呼ばれたときにレースコンディションになってしまう

Prototype

  • implements Cloneableしてもcloneメソッドの実装が必ず必要なわけではない
  • 印付けのみ(marker interface)
  • java.lang.Cloneable の clone はシャローコピー
  • ディープコピーする場合は自分でオーバーライドする必要がある
  • その場合はsuper.clone()を呼んでから
  • clone はコンストラクタを呼ぶわけでではないので、コンストラクタで
    フィールド操作以外の特殊な処理をしている場合は、それ相当の処理をオーバーライドした
    cloneで実装する必要がある

Builder

Abstract Factory

  • コンストラクタは継承されない

Bridge

  • 機能の階層 と 実装の階層 を分離する
  • いまいちピンとこない

Strategy

  • ロジックの根幹を入れ替える

Composite

  • 再帰を継承で表現

Decorator

  • 元々のインターフェースを多層的に実装し続けて機能追加することができるため、API(I/F)は変わらない

Visitor

  • 機能とデータ構造を分離する
    • Compositeはデータ構造クラスに処理を書いていた
  • VisitorとEntryが相互に呼び出しあって再帰処理する
  • Visitorがvisitする際にEntryにthis(Visitor)を渡してacceptさせる
    • Entryは渡されたVisitorをvisitすることでacceptとする
      • visitする際に先があればそこで再帰となる
  • acceptとvisitの相互の関係性を"double dispatch"という
  • 機能と処理を分離することで開放閉鎖原則に
  • Visitorの追加は簡単
  • Elementの追加は困難
  • Stringクラスは継承できない
    • 開放閉鎖原則を破っているが、これは最適化など効率のため

Chain of Responsibility

  • 処理クラスをデイジーチェーンにする方式
  • いまいちピンとこない

Facade

  • インターフェースや継承は使わない
  • 一連のクラスの手続きを一つの窓口クラスのメソッドに任せる
  • 初期化の順序など、ちゃんと設計していない(複雑になりすぎてしまった)せいで
    暗黙知となりがちなノウハウを手続きメソッドで明文化する

Mediator

  • 多数のステークホルダー(例えばダイアログに載ったUI部品群)が、相談役(Mediator)を通じて、
    どこかで起きたイベントを受けて協調して動作するための仕組み
    • 相談役は全てのステークホルダーを生成し、それぞれに自分が相談役であることを設定する
    • それぞれのステークホルダーは、
      • 他のステークホルダーが変化したときのハンドラと
      • 自分が変化したときに相談役に通知する処理
    • を実装する

Observer

  • 観察者(Observer)と観察対象
    • 観察対象に観察者を登録
    • 観察対象に変化があったら観察者へ通知する
  • 通知された際の観察者の挙動が観察対象に影響する場合は、無限ループに注意
  • インターフェースを通じてつながっているので、具象クラスは相互とも交換可能
  • Pub-Subの呼び名のほうが適切かも
  • GUIのMVCのMとVもこの関係といえる

Memento

  • スナップショットの保存とリストア
  • wide interface
    • 保存とリストアに使用
    • 対象のクラスの内部までアクセス可能
  • narrow interface
    • 保存トリガーと最小限の参照のみ可能
    • 変更はできない
  • この本ではアクセス修飾子で実現
  • スナップショットの中身はバージョンアップで変化していく

State

  • 状態の種類を各クラスで定義する
  • 状態の形はインターフェースで規定する
  • 現在の状態をコンテキストとして保持し、状態の変化をコンテキストのスイッチ(状態クラスの入れ替え)で行う。
  • 条件分岐で状態の区別を行う必要がなくなる
  • 誰が状態遷移するか
    • 各状態クラス?
      • この場合は各状態クラスが他の状態クラスを知る必要がある
        • 結合が強まる
    • 全状態を知ってるクラス?
      • これも似たようなもの
    • 状態遷移テーブル
  • 状態の追加は容易

Flyweight

  • 使いまわしできるインスタンスを共有する
  • インスタンスの変更は使用箇所全てに影響する
  • intrinsicな情報
    • どこで参照しても同内容となるような本質的な情報
  • extrinsicな情報
    • 状況に応じて変化する非本質的な情報
  • Mapに入れるとGCの対象ではなくなる?

Proxy

  • 代理人と本人で同じインターフェースを用意する
  • 本人じゃなきゃ出来ないことを呼ばれるまでは代理人が処理する
  • ここまで virtual proxy パターン
  • 遠隔にいるもの(呼ぶのに準備がいるような)を透過的に呼べるようにするのが remote proxy パターン

Command

  • コマンドをクラスで表現
  • コマンドの羅列でひとまとまりの処理を表現
  • 羅列をスタックにすることでUndoなど楽に実現

Interpreter

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment