忍者ブログ
[99]  [98]  [97]  [96]  [95]  [94]  [93]  [92]  [91]  [90]  [89
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

実家で読みました。
結城浩 著 『増補改訂版 Java言語で学ぶデザインパターン入門』
何かの役には立つだろうと思い、デザインパターンひと通り概観してみた。

で、以下は全パターンについて、個人的な備忘メモ。感想文じゃないね。


■Iterator
走査対象のクラスを集合体(Aggregate)と反復子(Iterator)とに分離する。それぞれがインタフェースか抽象クラスの走査のためのメソッドを実装する。
Aggregate->iterator()で反復子インスタンスを得る。
反復子のメソッド hasNext():Boolean, next():Object, prev():Objectなどを使って集合体内の要素を順に取り出す。
集合体と反復子が基本となるインタフェースを正しく実装している限り、走査対象の実装に因らず反復子で走査できるメリット(ex:後からリスト構造を異なるクラスに変更できる)。
ループを回す為にi,j,k...のような変数を増やす必要が無くなり、現在のインデックスを保持した複数のIteratorオブジェクトがそれを担う。

■Adapter
要はWrapper。
Adapterは必要な機能を持ったクラスインスタンス(Addaptee)を内部に保持(それはsuperの場合もある)し、必要とされるAPIの実装においてその機能を呼び出して使う。
古いクラスに直接手を加えずに、新しい環境に適合させることが出来る。

■Template Method
抽象クラス内の具象メソッド(Template Method)で他の抽象メソッドの実行手順(ロジック)を予め定義しておく。するとそのサブクラスは具体的な機能を実装するだけで、共通の手順で実行させるメソッドが得られることになる。
処理の流れが共通したクラスにおいて、それぞれをテンプレートたるクラスのサブクラスとすることで、ロジックの記述を1回で済ませる事が出来る。
また、それらサブクラスをスーパークラスのインスタンスとして同一視したうえでTemplate Methodを呼び出せる。

■Factory Method
抽象クラスFactoryの具象メソッド(Factory Method)の中で抽象クラスProductのインスタンス生成の手順を定義する。この1対のクラスを継承すると、異なるクラス間でインスタンス生成手順を共通化させることが出来る。
Factory変数(インスタンス参照)はFactoryと対となるProductの実体について知ることなく、インスタンスの生成を行うことが出来る。
仕組みや手順のみを提供するFactory,Productのようなクラス群をフレームワークというのだそうだよ。

■Singleton
コンストラクタを外から呼び出せないようにして、インスタンスの数を限定する。
マルチスレッドで利用する場合、インスタンスが生成されるタイミングに注意する。

■Prototype
フレームワークとして抽象メソッドManagerとProductがある。Managerに文字列などをキーとしてProductインスタンスを管理させる。ClientはProductサブクラスのコンストラクタを呼び出す代わりに、Managerはキーに対応するインスタンスを複製してClientに渡す。
Prototypeとなるインスタンスの状態とキーを対応づけて(本来のクラス名から離れて)新たなインスタンスを生成することが出来る。
使用する言語にclone()が無かったらClonableインタフェース(只のマーカとしてではなくclone()メソッドを持つような)を自分で実装しなきゃいけないなあ。

■Builder
Template Methodパターンにおいてロジックを定義していた具象メソッドを切り出してDirectorクラスとしてまとめる。一方で各手順に相当する抽象メソッドはBuilderクラスのサブクラスで実装する。
DirectorはBuilderを参照するフィールドを持つが、Builderの実体について知ることなく指示を出すことが出来る。また、後から別のBuilderに切り替えることも出来る。

■Abstract Factory
全体的な構成が同じで、それを構成する要素が異なるような場合に使う。
各要素を表す抽象クラスと、その要素の組み合わせ方を表す具象メソッドと各要素を生成するための抽象メソッドをもAbstract Factoryたる抽象クラスを一組として、これらを継承・メソッドを実装して使用する。なんのことやら。
ClientはAbstract FactoryのAPIのみを使用することで、Abstract Product(s)を得られる。つまり具体的なFactory同士は交換可能。
FactoryのcreateするProductを新たに追加するのはサブクラスが多いほど困難になる。

■Bridge
機能(APIの使い方・組み合わせ方)のクラス階層とAPI実装のクラス階層を分離し、機能クラスから実装クラスのAPIを使用(Bridge)する。
継承関係における任意の段階のクラスから任意の実装を使用できる、という利点。

■Strategy
Strategyインタフェースを実装し、複数のアルゴリズムをクラス化して切り替え可能にする。
状況に応じて動的にアルゴリズムを切り替えられる利点。

■Composite
Componentを継承したLeafとComposite(複数のComponentを集約する)により、ツリー状の構造をつくる。
Compositeを再帰的に処理することで、単数および複数のComponentを同等に扱うことが出来る。

■Decorator
核となる機能を持つクラスと、その実装を修飾するクラスとを同一視することにより、修飾の組み合わせを柔軟にする。
Decoratorたるクラスは内部に基底クラスまたはインタフェース(component)への参照を持ち、Decoratorの基底APIが呼び出されると具体的な実装はcomponentに委譲し、その前後に修飾動作を実行する。
新しい機能の追加が容易になり、また機能同士を動的に組み合わせることがが可能。

■Visitor
リスト状、ツリー状などのデータ構造の各要素(Element)に対して処理を行う際に、処理を行う部分をVisitorクラスとして分離する。VisitorのAPIを実装することで、要素に対する処理の追加を容易にする。
その際VisitorとElementは互いに、Element->accept()とVisitor->visit()を呼び出し合う。これによりElementはVisitorの実体について知る必要がなくなり、新しい処理(Visitor)の追加を容易にする。
VisitorはElementの実体を確認し、処理を分岐させる(あるいはメソッドをオーバーロードする)。故にElementのサブクラスを新たに追加するのは難しい。

■Chain of Responsibility
ある要求に対する処理をクラス(Handler)として独立させ、Handlerは要求を処理できない場合に、処理を委譲する別のHandlerへの参照を持つ。Handler->next:Handler のように。
条件による分岐をHandlerのメソッドの連鎖的な呼び出しに置き換えられる。Clientは実際に要求を処理するHandlerにまで気を遣う必要がなくなる。のかなあ。

■Facade
クラス同士の複雑な連携からなる機能を、窓口となるクラス(Facade)にまとめ、隠蔽し、ごくシンプルなAPIから実行出来るようにする。
メソッドの実行順序などの特殊で複雑なノウハウをコードとして明文化する役割。(?)

■Mediator
オブジェクト同士が互いに影響し合いながら動作するような状況にあって、仲介役としてMediatorインタフェース実装クラスを置く。互いに影響し合うオブジェクトはColleagueインタフェースを実装する。
Colleagueは状態の変化をMediatorに通知するようにしておき、その影響により他のColleagueに対して行う操作は全てMediator内に記述する。
オブジェクト間の相互作用に関するロジックを一つのクラスに集約させることが出来るという利点。

■Observer
状態の変化を監視する必要があるときに、何らかの状態を持つSubjectインタフェースと、その状態の変化の通知を受けるObserverインタフェースに分離する。2つのインタフェースは互いの具体的実装について知らないので、状態の具体的実装と変化通知の取り扱い方の変更や、それらの動的切り替えを容易に出来る。
基本的に、ObserverはSubjectから受ける通知のタイミングに因らず、通知の内容に応じた一定の動作をすることが求められる。
MVCにおいて、ModelがSubjectに、ViewがObserverにそれぞれ対応する。ModelはViewに対して内部状態の変化を通知し、表示形式に反映させるよう促す。

■Memento
インスタンスの状態をMementoクラスに保存し、カプセル化を破壊することなくUndoを行えるようにする。状態を保存するクラス(Originator)は現在の状態をMementoインスタンスとして出力するメソッドと、Mementoインスタンスを読み込み状態をある時点に戻すメソッドとを持つ。(Originatorの各フィールドはprivateのままにできる。)
MementoのAPI(コンストラクタ含め)は極力Originatorからのみ利用するようにし、publicメンバは最低限にとどめる。
状態をインスタンス化しておくことで、Undoのステップ数の増減やシリアライズ機能の追加などを容易にできる。

■State
Contextインスタンスに関わる状態の変化によって、Contextの複数のメソッドの動作を切り替える必要がある場合に、メソッド中で条件分岐を行うのではなく、各状態をStateインタフェース実装として分離し、Contextの動作をStateインスタンスのメソッドに委譲する。わかりにくい。
State間の状態遷移を管理するクラス(State実装クラス自身の場合もある)は、少なくとも2つ以上のState実装について知っている必要がある(強い結合が生じる)。

■Flyweight
インスタンスの状態が生成される状況に依存しない場合に、Flyweightクラスとして予めプールしたインスタンスを共有することで、インスタンス生成にかかるリソースを節約する。
インスタンスへの新しい参照が必要なときは、FlyweightFactoryクラスに要請することで新たに生成したインスタンスまたはプールされた生成済みのインスタンスへの参照が渡される。

■Proxy
ある機能を持った主体となるクラス(RealSubject)の生成にかかるリソースが無視しがたいという状況下で、SubjectのAPIを実装したProxyクラスを代理に立て、具体的な機能が必要になるまでRealSubjectの生成を後回しにする。Proxyはメソッドの呼び出しに対し、フィールドの書き換えなどについては代理で行い、RealSubjectの機能が必要となった時点でインスタンスを生成し、委譲を行う。
SubjectからProxyを分離することにより、ProxyクラスだけでRealSubjectの生成のタイミングを調整できる。
ProxyはRealSubjectのコンストラクタを呼び出すため、Subjectの具象クラスについて何らかの方法で知る必要がある。

■Command
命令をCommandインタフェースの実装としてオブジェクトにすることで、個々の命令の実行順序などの管理を容易にする。インスタンス生成後、Command->execute()のように実行。
Compositeパターンと組み合わせて複数のCommandを実行したりとか。

■Interpreter
ミニ言語セットと構文解析プログラムのみを作成し、ロジックの修正はミニ言語で行う。
使いどころがいまいち分からないなあ。

PR
この記事にコメントする
お名前
タイトル
文字色
メールアドレス
URL
コメント
パスワード   Vodafone絵文字 i-mode絵文字 Ezweb絵文字
この記事へのトラックバック
この記事にトラックバックする:
26歳のハローワールド
カレンダー
04 2024/05 06
S M T W T F S
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
最新コメント
[11/27 gyzwviyehl]
[11/18 Tepexaxyonelo]
[09/12 gomFolley]
[08/16 CypeBachCoece]
[06/02 gb]
[03/06 kishima]
[01/18 KNDY]
[01/16 kage]
[12/23 KNDY]
[12/23 kage]
最新トラックバック
ブログ内検索
アクセス解析
プロフィール
HN:
knd
HP:
自己紹介:
絶賛迷走中。
UNIQLO CALENDAR
忍者ブログ [PR]