DesignPattern


Javaでコーディンしないようになって大分経つので、C++に偏った解説になっています。
デザインパターンは、解釈の仕方によっては適しているいないが論議になったりします。
(有名な書籍とかもwebで反論されていたりします。第三者的に見ると、取り方次第な批判だと思うことが多いです)
自分は本も読みましたが、webサイトから得た情報の方が多いかも知れません。
Gofとかの原著を読んでみると、正しい彼らの主張が判るかも知れません。
やっぱ英語出来ないとダメか?>俺

C++に当てはめているので、純粋仮想関数のデフォルト実装無しの場合インターフェイスとして扱っています。
デザインパターンとしておかしいという指摘がありましたら、掲示版にお願いします。



構造に関する物


■Adapter

インターフェイス部の違うクラスの間に入ってアダプターの役目をするクラスを作ります。


継承の場合(is-a)
Clietn

Uses
<<interface>>
Target
 
targetFuncA
targetFuncB




implements
Adapter
 
targetFuncA
targetFuncB



extends

Adaptee
 
funcA
funcB
funcC

 
メンバーで持つ場合(has-a)
Client

Uses
<<interface>>
Target
 
targetFuncA
targetFuncB

|
|
|

extends
Adapter
 adaptee
targetFuncA
targetFuncB

|
|
has

Adaptee
 
funcA
funcB
funcC



既存のadapteeに手を入れない為のもので、既存で完成度が高いクラス、またはデバッグ(ビジネス系では単体テストとかUTとか)をしっかりしたクラスなどを変更したくない場合使います。


■Bridge

インターフェイスを実装する継承と、普通の継承を分けて、それらをコンポジションで橋渡しをします。

Abstraction
implementor
funcA
funcB
◇→
<<interface>>
Implementor
 
impFuncA
impFuncB

|
|
|



RefineAbstraction
 
refineFuncA
refineFuncB
ConcreteImplementor
 
impFuncA
ipmFuncB

クラスの拡張と、実装の二つを分けて考え、結びつけには包含を使います。
包含の依存性の低さを使ってうまく橋渡しと言った感じです。



■Composite

階層構造を表すのに適したパターンで、nodeとそれに格納されて居る物を同一視するために継承を使います。


Client
 
 
Uses
--------→
Component
 
funcA
funcB
add
remove
getChild
←---------------
|
|
|
|
 
 
・・・・


・・・・・
 
 
・・・・・
|
|
|
Leaf
 
funcA
funcB
Composite
children
funcA
funcB
add
remove
getChlid
|
|
|
◇--



ディレクトリとファイルの関係と考えると解りやすいです。childrenはComponetの集合体になると思います。
add の基底実装は例外を投げる形になります。これはnodeになるCompositeには追加機能は要りますが、格納物になるLeafにはその機能は有っては いけません。でも、基底のComponentに無いとClientが使うときCompositeにキャストしなければならないからです。getChild はNULLポインターを返すとかが良いかと思います。





■Decorator

同じインターフェイスを持つクラスに装飾を着けながら、再帰的に利用します。


Component
 
funcA
funcB
←---------------
|

|
 
 
・・・・


・・・・・
 
 
・・・・・
|
|
|
ConcreteComponent
 
funcA
funcB
Decorator
component
 
|
|
|
◇--

|
ConcreteDecorator
 
funcA
funcB



Compositeと同じ要領で再帰構造を作り、装飾の入れ子を実現します。
コンストラクターで同一インターフェイスを持ったオブジェクトを持たせる事で、何重にも包んでいく形で機能を追加できます。




■Facade



■Flyweight



■Proxy



■Template Method

基底クラスで大まかな枠組を決め、継承して使います。

AbstractClass
 
funcA
funcB
templateFunc

|
ConcreteClass
 
funcA
funcB


上記の例ではtemplateFuncを呼ぶと決まった順番でfuncAとfuncBが呼び出されます。
C++の場合は純粋仮想関数はprotectedにしておく方が良いかも知れません。
ロジックが似ていて、継承先で様々な違いを実装できる為、多態(ポリモフィズム)を実現するのに適したパターンだと思います。
直接仮想関数をよばない所が、実装に幅を持たせると思います。



生成に関する物


■Factory Method

Template Methodのパターンでオブジェクトを生成します。

Creator
 
create
factoryMethod
Creates
<<interface>>
Product
 
funcA
funcB

|
|
|



ConcreteCreator
 
facotryMethod
Creates
ConcreteProduct
 
funcA
funcB

オブジェクトの作り方を大まかに決めておくパターンで、生成者と生成物の基底セットを作っておき、両者を継承して実装します。
オブジェクト生成に伴う、管理情報の登録などをする時に良いと思います。
productで宣言した仮想関数を待つ物を作る工場セットと言った感じでしょうか。
利用者側は両基底クラス側を使い、派生先のオブジェクトを多態で生成出来るので、仮想コンストラクターと言った感じでしょうか。



■Singleton

オブジェクトを一つしか作れないようにします。

Sigleton
-singleton
-Singleton
+getInstance


// Java だとこんな感じ(らしい)---------------------------
public class Singleton{
    private static Singleton singleton = new Singleton();
    private Singleton(){}
    public static Singleton getInstance(){
        return singleton;
    }
}
// ------------------------------------------------------
// C++ --------------------------------------------------
class CA{
  CA(){}
  static CA* pObj;
public:
  static CA* getObj(){
    return pObj;
  }
};
CA* CA::pObj = new CA();
// ------------------------------------------------------

Javaのデザインパターンの本は多く出回っていて、C++のデザインパターン書籍は少ないです。
(凄くメジャーなC++を言語に選んだデザインパターン本もありますが)
Java のデザインパターン本を読んだC++プログラマーが、C++でSingletonを実装しようとした時に、メンバー変数にそのクラスへのポインターを初期 値NULLで持ち、オブジェクト生成したらそこを指すようにして、生成前にif文でNULLチェックするという方法が取られる事があります。
(webサイトで何件か見受けました)
この実装の場合は厳密にはシングルトンにはなりません。
シングルスレッド環境だった場合には問題ないのですが、マルチスレッド環境だった場合は、NULLチェックOKでnewする直前で他のスレッドのNULLチェックに行ってしまったりすると、シングルトンが成立しません。

全ての実装をクラス内に書かなければならないJavaと違って、グローバル変数とあまり変わらない気もしますが。




■Prototype

クラス名を指定せずにコピーを作ります。

Client
 
 
Uses
<<interface>>
Prototype
 
createClone

|
ConcretePrototype
 
createClone


ポインターや参照の先のクラス名が解らなくても、オブジェクトをコピーする事が出来ます。
createClone関数はコピーコンストラクターのような実装になると思います。
コピーコンストラクターの仮想関数化って感じでしょうか。



■Builder

建築家(ビルダー)と現場監督(ディレクター)という感じのパターンです。

Director
builder
construct
◇→
<<interface>>
Builder
 
funcA
funcB
getResult




ConcretePrototype
 
funcA
funcB
getResult


雇主(利用者)は建築家を決めて、現場監督に斡旋し、建築(construct)をしてもらいます。
雇主は建築家の管理は現場監督に任せてしまいます。現場監督は、雇主に紹介された建築家の素性を知りません。ので、「オフィス空間のデザインは彼でいいが、生活空間は別の建築家を使うおう。」なんて雇主の意見が通る仕組みなっています。


■Abstract Factory

工場も製品も抽象化というパターンです。

※UML的に線の引き方は正しくないかも知れません。(って言うか多分正しくない)
Creates
------------
|
|
Creates
------------------
|
|
Creates
------------------
|
|
<<interface>>
AbstractFactory
 
createProduct1
createProduct2
createProduct3
<<interface>>
AbstractProduct1
 
execute1
execute2
<<interface>>
AbstractProduct2
 
doAlpha
doBate
<<interface>>
AbstractProduct3
 
performOne
performTwo

|
|
|
|

|

|

|
|
|
ConcreteProduct1
 
execute1
execute2
ConcreteProduct2
 
doAlpha
doBate
ConcreteProduct3
 
performOne
performTwo
|
|
|
|

|
|
------------
Creates



|
|
------------------
Creates

|
|
------------------
Creates
ConcreteFactory
 
createProduct1
createProduct2
createProduct3


工場と製品を抽象化してセットにしておけば、利用者側は基底の工場に発注し基底の製品として貰えば、多態な一式が貰えるというものです。



振舞に関する物


■Iterator

イテレーターとそれを返す集合体のインターフェイスを設け、継承して実装します。

<<interface>>
Aggregate
 
iterator
Creates
<<interface>>
Iterator
 
hasNext
next






ConcreateAggregate
 
iterator

←◇
ConcreateIterator
aggregate
hasNext
next

STLでも有名なパターンです。
集合体とアクセスに使うものを分けて、汎用性を高めています。
パターン的には、継承実装した物同士が互いに関連と集約しあうという関係になりますが、使用者にはその部分は見えず、インターフェイスから先の仕様変更に影響が出ません。
STLの様にイテレーターの[]演算子をオーバーロードしたりして、カスタマイズすると良い感じかも知れません。



■Strategy

戦略と言う概念のオブジェクトを持ちます。
Context
strategy
contextFunc
◇----------→
Strategy
 
strategyFunc
 
 
・・・・・


・・・・・
 
 
・・・・・

ConcreteStrategy1
 
strategyfunc
ConcreteStrategy2
 
strategyfunc

アルゴリズム部分を他の部分から切り離します。
アルゴリズムの載せ変えを出来るように、コンポジションにする事で取り外し可能にします。
実行中の切替えが出来るように組めるのが、利点が高いと思います。




■Interpreter



■Chain of Responsibility



■Command



■Mediator



■Memento



■Observer



■State



■Visitor



戻 る