デザインパターン一言メモ

Adapter

IAdapterがAdapteeに委譲。

継承で実現する場合もある。

Prototype

IPrototypeが自身を複製。

Memento

OriginatorがMementoを作成、復元。

State/Strategy

IState/IStrategyでポリモーフィズム。

具体的にはclientからIState/IStrategyを利用し、インスタンスもclient内で生成することが多い。
インスタンス生成時に条件分岐等でアルゴリズムの切替え、状態の切替えを実施。

Decorator

IComponentを共通で実装。
ConcreateComponentからDecoratorに処理を委譲。

Composite

IComponentを共通で実装。
CompositeとLeafがある。
CompsiteがIComponentのコレクションを保持。

Proxy

ISubjectを共通で実装。
Proxyが自分で処理をすることも必要ならRealSubjectに処理を委譲することもできる。

Flyweight

FlyweightFactoryでFlyweigthインスタンスを生成し自身のpoolコレクションに保存。
利用時も既にインスタンスが存在すれば、それを利用する。

Singleton

コンストラクタをprivateにする。
自身のstaticメンバーにインスタンスを保存

Iterator

IIteratorにIAggregateのコレクションを保持する。
IAggregateでIIteratorのインスタンス生成して利用する。

Template Method

テンプレートメソッドはabstractメソッドのみ使う。
サブクラスでabstractメソッドを実装。
スーパークラスがサブクラスをコントロール。

Builder

DirectorはIBuilderで定義したメソッドのみ使う。
DirectorがBuilderをコントロール。

Factory Method

Template Methodと同じ構造。
インスタンス生成が必要な部分をサブクラスで実装。

Factory抽象クラスの中で実装したcreateで抽象createProductなどインスタンス生成の手順を定義し、サブクラスでcreateProductを実装する。

インスタンス生成のコントロールを得るという点から下記のような方法が有名。
(Factory Methodをパラメータ化)

Class Test {
Test(int type){
_type = type;
}
}

Class Test{
private Test(int type){ //コンストラクタをprivate
_type = type;
}
static create(int type){ //インスタンス生成メソッドを準備
return new Test(type);
}
}

Abstract Factory

IFactoryでIProduct1,IProduct2の生成を定義。
どのような部品セット(1,2)なのかをIFactoryで定義し、IProductでそれぞれの処理を定義。

Bridge

継承と実装を分離。
機能追加は、Abstractionを継承したRefinedAbstractionに。
実装は、Abstractionより委譲されたImplementorに。

Visitor

IVisitorはデータ構造ごとのvisitを実装する。
IAcceptorのacceptの中でvisitを呼び、自身をvisitに渡す。
ダブルディパッチ。

Chain of Responsibility

IHandlerは転送先のIHandlerを自身に持ち
処理が完了か次が見つからないとき以外は次に転送し続ける。

Facade

サブシステム化し、単純な窓口を提供。

Mediator

IMediatorでIColleaugeを生成しメンバーとして保持、さらにIColleauge.SetMediatorで自身を渡す。
IColleaugeは自身に変更があったらIMediator.ColleagueChangedでIMediatorに通知。
IMediatorはColleagueChangedが呼ばれたとき、保持するIColleaugeすべての状態からロジックを判断する。

Observer

ISubjectがIObserverを保持しISubjectが変化したらIObserver.Updateを呼ぶ。
被験者が観察者のインスタンスを保持する。

Command

処理の呼び出しをメッセージからオブジェクトにする。

ICommandはExecuteを定義し、Receiverを保持。
Receiverは実際のActionを定義しICommand.Excuteの中でReceiver.Actionを呼ぶ。
Invokerは起動者でボタンのようなイメージ。

Interpreter

独自構文の文字列をContextに渡しトークン解析する。
ContextはhasNextやnextTokenなどで解析したトークンを取得できる。

構文解析クラスは文法ごとにIAbstractExpression実装した
TerminalExpression、NonterminalExpressionを準備。
NonterminalExpression1、NonterminalExpression2、TerminalExpression
のようにそれぞれ作成する。

実際は、
NonterminalExpression1.Parse(new Context(文字列))のように渡されると、
NonterminalExpression1の内部でnew NonterminalExpression2.Parse(context)
のように最後のTerminalExpressionまで内部で呼ぶ。

Null Object

IAbstractionをRealObjectとNullObjectが実装。
IAbstraction.Request()でRealObjectを返すが、Request()がNullを返す場合はNullObjectを返す。

C# 設計メモ

順不同。思いつたら更新。

・クラスの単位

GUIのフォーム単位のクラスが基本(GUIがなければユースケース管理)で、その中で必要に応じてクラスに抜き出す。

1.変更の発生しそうな部分をクラスに抜き出す。
拡張ポイント(DI)

2.共通で使う部分をクラスに抜き出す。
アダプター(合成+委譲)で共通化
ストラテジー

3.他クラスから参照される部分をクラスに抜き出す。

4.テストしたい部分をクラスに抜き出す。

5.インスタンス生成をクラスに抜き出す。
生成処理を1箇所にまとめることで変更に対応しやすく。
DIが連続して上位レイヤーに引数が溢れてきたら。
(作ると使うを分ける)

6.プリミティブな値に型定義する場合。
値オブジェクト

・クラス、インターフェース、メソッド

参照と変更を分ける(CQS)。意味のある名前にする。スコープが大きいのに一文字変数名や、ハードコーディングしている数値など避ける。とりあえずメソッドは小さく。

・レイヤー

適切にクラス分けしていけば最終的に自然とレイヤーに当てはまる形になっているのでそれほど意識しない。

・依存関係のコントロール

クラス間の依存をインターフェースへの依存にすること。派生クラスの追加で対応する。拡張ポイントと呼ぶ場合もある。

 

・DB系

DBの依存関係。FKがある方が依存している。依存している方が子。PKは重複できないけど、FKは重複できるので、FKある方が多。

複合主キーとなっている関係従属を取り除く正規化は当たり前に発生するので、正しいモデリングをすると必然的に複合主キーが現れる。サロゲートキーを入れる場合、制約はアプリ側で対応する。例えば仕入価格を、仕入先・商品・開始年月で識別するような場合。

参照整合性。実務では完全な制約が必要ではなく、緩い制約の方が都合がいいときもある。ただし、構造が壊れやすくはなるので注意。

C# Interpreter

C# デザインパターン Command

ざっくりまとめると、commandにreceiverを渡す。(commandがreceiverを保持)
渡し方は、Command cmd = new ConcreateCommand(receiver)
あるいは、上記のようなSetReceiver(receiver)とか。
そして、commandのExecute()の中でreceiverのAction()を呼ぶ。
Invokerは呼び出しで、そこからcommandのExecute()を呼ぶ。
処理の実体はreceiverのAction()の中。

C# Proxy

C# Flyweight

C# State

C# Memento

C# Observer

C# Mediator