Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 5 years have passed since last update.

オブジェクト指向における再利用のためのデザインパターン(改訂版)

Last updated at Posted at 2018-12-10

#諸言
 学習履歴全体のリンク
 https://qiita.com/shigural/private/444b991293e5ab1b40af
#本文
##オブジェクト指向における再利用のためのデザインパターン(改訂版)
このサイトがものすごくわかりやすい(特にソースコード)
https://myenigma.hatenablog.com/entry/20140809/1407568602

##デザインパターン一覧
一覧.jpg

##デザインパターン関連図
関連図.jpg

###01.AbstractFactoryパターン(Kit)
目的:互いに関連したり依存し合うオブジェクト軍を、その具象クラスを明確にせずに生成するためのインタフェースを提供する
構成:基底クラスAbstractFactoryから派生するいくつかのConcreateFactoryクラスは、指定したオブジェクトのポインタをを返す。ConcreateFactoryクラスの種類により該当のオブジェクトは変化する。ConcreateFactoryクラスのメンバ関数はオブジェクトを生成し、そのポインタを返すのでクライアントはそれを利用する
実装:ConcreteFactoryクラスのインスタンスは1つしか必要としないため、Singletonパターンにより実装する。

01AbstractFactory.jpg

###02.Builderパターン
目的:複合オブジェクトについて、その作成過程を表現形式に依存しないものにすることにより、同じ作成過程で異なる表現形式のオブジェクトを生成できるようにする
構成:Builderクラスからは複数のConcreteBuilderクラスが派生する。クライアントはDirectorクラスを呼び出し、Directorクラスの持つ、Builder型引数のメンバ関数を通じてDirectorクラスのメンバ関数に渡す。これにより、渡す引数の型によってDirectorの動作を変化させることができる
実装:Builderクラスのメソッドはデフォルトで空にしておき、純粋仮想関数にはしない。必要がある場合だけオーバーライドさせるように設計する
02Builder.jpg

###03.FactoryMethodパターン(Visual Constructor)
目的:オブジェクトを生成するときのインタフェースだけを規定して、実際にどのクラスをインスタンス化するかはサブクラスが決めるようにする。Factory Methodパターンはインスタンス化をサブクラスに任せる
構成:クライアントはCreatorクラスから派生したConcreteCreatorクラスをCreator型として生成する。その後、生成したCreatorオブジェクトのFactoryMethod関数を呼び出す。これは複数のパラメータを受け取り、その条件からオブジェクトを生成してポインタを返す関数である。クライアントはFactoryMethod関数から帰ってきたproductのポインタを扱う。
実装:CreatorクラスをConcreteCreatorクラスとセットにして、はじめから具象クラスであるCreatorクラスを生成しても良い。むしろこの方が一般的である。
03FactoryMethod.jpg

###04.Prototypeパターン
目的:生成すべきオブジェクトの種類を原型となるインスタンスを使って明確にし、それをコピーすることで新たなオブジェクトの生成を行う
構成:クライアントはまず、Prototypeクラスから派生する任意のConcretePrototype型のオブジェクトを生成する。これをmap型のある変数に記録する。続いて、ConcretePrototypeクラスの持つClone関数を呼び出す。Clone関数は自身のコピーを生成してそのポインタを返す関数である。クライアントはClone関数により帰ってきたポインタを利用する
04Prototype.jpg
推奨:http://marupeke296.com/DP_Prototype.html
間違っている(Prototypeマネージャについて正しいが、Cloneされない):
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Prototype/Prototype.cpp

###05.Singletonパターン
目的:あるクラスに対してインスタンスが1つしか存在しないことを保証し、それにアクセスするためのグローバルな方法を提供する
構成:Singletonクラスは静的関数Instanceと静的変数_instanceを持つ。Instanceが実行されると_instanceがnullptrの場合に限り新たなSingletonオブジェクトを生成し、_instanceはそのポインタとなる。また、このときInstanceは_instanceを返す。
実装:Singletonのより柔軟な実装としてオブジェクトの登録機構を用いる方法がある。

class Singleton{
public:
 static void Register(char *name,Singleton*);
 static Singleton* Instance();
protected:
 static Singleton* Lookup(const char* name);
private:
 static Singleton* _instance;
 static List<NameSingletonPair>* _registry;
}

上記のようにSingletonを作っておき、Singletonを利用するクラスはすべて静的に定義しておく。
(コンストラクタではRegister("name",this)とする)
そして、Singletonを利用するときにはLookupで帰ってきたポインタにアクセスすれば良い。

05Singleton.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Singleton/Singleton.cpp

###06.Adapterパターン(Wrapper)
目的:あるクラスのインタフェースを、クライアントが求める他のインタフェースへ変換する。Adapterパターンは、インタフェースに互換性のないクラス同士を組み合わせることができるようにする。
構成:
<クラスに対するAdapterパターン>
Adapterクラスは2つの互換性のないクラスを多重継承してつくる。Adapterクラスは適合対象であるクラスの関数をオーバーライドして、適合元の関数を実行する。
<オブジェクトに対するAdapterパターン>
Adapterクラスは適合対象であるクラスを継承し、適合元のクラスを持つことで実現する。適合対象の関数はAdapterクラスによりオーバーライドされ、適合元のクラスが呼び出される。
06Adapter.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Adapter/Adapter.cpp

###07.Bridgeパターン(Handle/Body)
目的:抽出されたクラスと実装を分離して、それらを独立に変更できるようにする
構成:Abstractionクラスは抽象されたインタフェースを定義し、それをRefinedAbstractionクラスは継承する。AbstractionクラスはImplementorクラスへの参照を保持し、Implementorクラスの具体的な実装であるConcreteImplementerクラスの処理が実行される。
実装:Implementerクラスのインスタンスを生成する方法はいくつかある
1.Abstractionクラスのコンストラクタに渡されるパラメータに基づいて1つの実装をインスタンス化する。
2.最初にデフォルトの実装を選択しておき、後で必要に応じて変更する
3.決定を他のオブジェクトに完全に委譲する(AbstractFactoryパターン)
また、Implementerオブジェクトを複数のBridgeパターンで共有するために最も一般的な方法は、参照の回数を保持することである。

Handle& Handle::operator= (const Handle& other){
 other._body->Ref();
 _body->Unref();//_bodyは参照の回数を数える

 if(_body->RefCount()==0)delete _body;
 _body=other._body
 return *this;
}

07Bridge.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Bridge/Bridge.cpp

###08.Composite
目的:部分―全体改装を表現するために、オブジェクトを木構造に組み立てる。Compositeパターンにより、クライアントは個々のオブジェクトとオブジェクトを合成したものを一様に扱うことができるようになる。
構成:クライアントはComponentクラスを利用する。ComponentクラスからLeafクラスとCompositeクラスが派生されており、Compositeクラスは子のComponentクラスを保持する。
Compositeクラスは再帰的なフォルダ―ファイル構造、組み合わせ図形など実装などに用いられる。
実装:走査するディレクトリ構造の保持としてはInterpreterパターンが一例となるが、多くの場合は親オブジェクトにも子オブジェクトにもlistをもたせておくと良い
08Composite.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Composite/Composite.cpp

###09.Decoratorパターン(Wrapper)
目的:オブジェクトに責任を動的に追加する。Decoratorパターンは、サブクラス化よりも柔軟な機能拡張方法を提供する
構成:Componentクラスには一般的なインタフェースが定義される。Componentクラスを継承したConcreteComponentクラスは複数あり、拡張された機能が実装される。Componentクラスを継承したDecoratorクラスはコンストラクタで任意のComponentクラスへの参照を受け取る。またDecoratorクラスからConcreteDecoratorクラスが複数派生する。
クライアントはConcreteDecoratorクラスを宣言するとき、コンストラクタでConcreteComponentクラスへの参照を与える。これにより任意のConcreteDecoratorクラスとConcreteComponentクラスを組み合わせることができる
実装:decoratorのインタフェースは装飾するcomponentのインタフェースと一致している必要がある。そのため、Componentクラスはできるだけ簡潔にしておく方が良い。
Componentクラスが重たく(量が多い)、Decoratorパターンを適用するにはコストが掛かりすぎる状況ではStrategyパターンを適用するべきである。
09Decorator.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Decorator/Decorator.cpp

###10.Facadeパターン
目的:サブシステム内に存在する複数のインタフェースに1つの統一インタフェースを与える。Facadeパターンはサブシステムの利用を容易にするための高レベルインタフェースを定義する。
構成:Facadeクラスは単純な処理をする複数のクラスを所有する。クライアントはFacadeクラスのインタフェースにさえアクセスすれば良い
10Facade.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Facade/Facade.cpp

###11.Flyweightパターン
目的:多数の細かいオブジェクトを効率よくサポートするために共有を利用する。具体的にはオブジェクトをDBに保存しておき、DBにないオブジェクトを生成するときにのみ新規生成して効率を改善する。
構成:クライアントはFlyaweightFactoryクラスとConcreteFlyweightクラス、UnsharedConcreteFlyweightクラスを持つ。FlayweightFactoryクラスは特定のキーが与えられたときにキーに対応するオブジェクトへのポインタを返す関数GetFlyweight関数をもつ。この関数では新規に与えられたキーの場合、新たにオブジェクトを生成する。
キーに対応するオブジェクトとして、Flayweightクラスから派生したConcreteFlyweightとUnsharedConcreteFlyweightが挙げられる。クライアントは、Flyweightクラスの派生クラスをFlyweightFactoryクラスを通じて生成する。この時共有オブジェクト(ConcreteFlyweightクラス)の場合には単にポインタを返すがUnsharedConcreteFlyweightを生成する場合にはnullptrを返すなどして固有であることを保証しなければならない。
11Flyweight.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Flyweight/Flyweight.cpp

###12.Proxyパターン(Surrogate)
目的:あるオブジェクトへのアクセスを制御するために、そのオブジェクトの代理、または入れ物を提供する。つまり、画像オブジェクトのように使われるまではダミーのものを入れておきたいときに用いる。
構成:クライアントはSubjectクラスから派生したProxyクラスのインスタンスを保持する。ProxyクラスはRealSubjectを持ち、Request関数が与えられたときにProxyかRealSubjectを使ってどのように処理するのかを定義する。
実装:C++では->演算子をオーバーライドすることができるので、Proxyクラスへの->演算子をオーバーライドしてRealSubjectへの処理に書き換えるとよい。(->の実装としてRealSubjectクラスの持つ関数をreturnすればよい)
12Proxy.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Proxy/Proxy.cpp

###13.ChainofResponsibilityパターン
目的:1つ以上のオブジェクトに要求を処理する機会を与えることにより、要求を送信するオブジェクトと受信するオブジェクトの結合を避ける。
受信する複数のオブジェクトをチェーン上につなぎ、あるオブジェクトがその要求を処理するまで、そのチェーンに沿って要求を渡していく。
構成:クライアントの持つHandlerクラスから派生する多数のConcreteHandlerクラスは、要求を処理で来るならば処理し、処理できなければ次のチェーンであるsuccessorポインタの指す対象に要求を渡す。
13ChainofResponsibility.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/ChainOfResponsibility/ChainOfResponsibility.cpp

###14.Commandパターン(Acition,Transaction)
目的:要求をオブジェクトとしてカプセル化することによって、異なる要求や、要求からなるQやログにより、クライアントをパラメータ化する。また、取り消し可能なオペレーションをサポートする
構成:クライアントはConcreteCommoandオブジェクトを生成し、それに対するReceiverオブジェクトを設定する。ConcreteCommandクラスはCommandクラスから派生している。
InvokerクラスはCommandクラスの派生クラスへのポインタを知っており、それに対してアクションを求めるとConcreteCommandクラスはReceiverオブジェクトを返す。
実装:Commandにはテンプレートを用いることができる。
14Command.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Command/Command.cpp

###15.Interpreterパターン
目的:言語に対して、文法表現とそれを使用して文を解釈するインタプリタを一緒に定義する。単純な文法で効率が重要でない場合に用いられる。
構成:AbstractExpressionクラスから派生するTerminalExpressionクラスとNonterminalExpressionクラスはそれぞれ終端記号と終端記号以外が先頭にあるかを認識し、該当する場合には元のテキストの持つ_outputを変更する処理を実装する。具体例は下記リンクを参照
15Interpreter.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Interpreter/Interpreter.cpp

###16.Iteratorパターン(Cursor)
目的:集約オブジェクトが基にある内部表現を公開せずに、その要素に準にアクセスする方法を提供する。
構成:クライアントはAggregateクラスとIteratorクラスを持つ。IteratorクラスはConcreteIteratorクラスを派生し、要素のアクセス・走査に必要なインタフェースを提供する。ConcreteIteratorクラスはIteratorクラスの実装およびカレント要素の記憶を行う。AggreteクラスはConcreteAggregateクラスを派生し、Iteratorオブジェクトを生成するためのインタフェースを定義する。つまりConcreteAggregateクラスの生成したConcreteLteratorインスタンスはConcreteAggregateオブジェクトのポインタを複数持ち、リストとして保持できる。
16Iterator.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Iterator/IteratorSample.cpp

###17.Mediatorパターン
目的:オブジェクト軍の相互作用をカプセル化するオブジェクトを定義する。Mediatorパターンはオブジェクト同士がお互いを明示的に参照し合うことがないようにして、結合度を低めることを促進する。それにより、オブジェクトの相互作用を独立に変えることができるようになる
構成:Mediatorクラスから派生するConcreteMediatorクラスはColleagueオブジェクトを保持しており、Collegueオブジェクトは他のCollegueオブジェクトとの通信を常にMediatorオブジェクトを介して行う。
実装:ColleagueとMediatorとの通信は方法が2つある。1つはObserverパターンを利用する方法で、もう一つはColleagueオブジェクトから直接に通信できるよう、Mediatorクラスに通知用のインタフェースを用意することである。(Mediatorクラスへのポインタはコンストラクタで与える)
17Mediator.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Mediator/Mediator.cpp

###18.Mementoパターン(Token)
目的:カプセル化を破壊せずに、オブジェクトの内部状態を捉えて外面化しておき、オブジェクトを後にこの状態に戻すことができるようにする。(つまりセーブ-ロードやリドュー-アンデュー)
構成:MementoクラスはOriginatorオブジェクトの内部状態を、必要な部分に限り保存する。また、Originatorオブジェクト意外によるアクセスから保護を行う。CaretakerクラスはMementoオブジェクトを保管し、必要な場合には走査の巻き戻し司令を行う。
実装:Mementoオブジェクトは変化した部分だけを変更したほうが高速である。
18Memento.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Memento/Memento.cpp

###19.Observerパターン(Dependents,Publish-Subscribe)
目的:あるオブジェクトが状態を変えたときに、それに依存するすべてのオブジェクトに自動的にそのことが知らされ、また、それらが更新されるように、オブジェクト間に一対多の依存関係を定義する
構成:SubjectクラスはObserverを知っており、任意のObserverがsubjectの変化に対応させられる。Observerクラスはsubjectが変化されたときのUIを定義しており、ConcreteSubjectクラスはオブジェクトにどのような影響を与えるか、どんな通知を送るかを知っている。ConcreteObserverクラスはConcrteSubjectオブジェクトへの参照を保持しており、ConcreteSubjectの状態と矛盾しないように保存、更新している。
実装:Observerパターンには変化があったときに即座にそれを通知する方法と、クライアントが適当なタイミングで更新オペレーションを呼び出す方法とがある。
19Observer.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Observer/Observer.cpp

###20.Stateパターン(Objects for States)
目的:オブジェクトの内部状態が変化したときに、オブジェクトが振る舞いを変えるようにする。クラス内ではふるまいの変化を記述せず、状態を表すオブジェクトを導入することでこれを実現する。
構成:Contextクラスは状態を表すConcreteStateクラスのインスタンスを保持する。Stateクラスから派生するConcreteStateクラスではContextクラスの1つの状態に関する振る舞いが実装される。
すなわち、あるクラスに対して専用の状態を表すクラス群を作り、なにか処理が行われるときにはその状態の関数を呼び出すように実装する
20State.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/State/State.cpp

###21.Strategyパターン(Policy)
目的:アルゴリズムの集合を定義し、各アルゴリズムをカプセル化して、それらを交換可能にする。Strategyパターンを利用することで、アルゴリズムをそれを利用するクライアントからは独立に変更することができるようになる
構成:Strategyクラスはすべてのアルゴリズムに共通のインタフェースを宣言し、ConcreteStrategyクラスはその実装を行う。ContextクラスはStrategyのオブジェクトに対する参照を保持して必要なものを利用する
実装:Contextクラスのコンストラクタでnew ConcreteStrategyAなどを引数として実装するb
21Strategy.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Strategy/Strategy.cpp

###22.TemplateMethodパターン
目的:1つのオペレーションにアルゴリズムのスケルトンを定義しておき、その中のいくつかのステップについては、サブクラスでの定義に任せることにする。TemplateMethodパターンではアルゴリズムの構造を変えずにアルゴリズム虫のあるステップをサブクラスで再定義する。
構成:AbstractClassクラスでは不変的な部分の実装を行い、純粋仮想関数として変化しうる処理を実装する。ConcreteClassでは変化しうる処理を実装する。
22TemplateMethod.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/TemplateMethod/TemplateMethod.cpp

###23.Visitorパターン
目的:あるオブジェクト構造上の要素で実行されるオペレーションを表現する。Visitorパターンにより、オペレーションを加えるオブジェクトのクラスに変更を加えずに、新しいオペレーションを定義することができるようになる
構成:Visitorは処理を行うためのクラスであり、Elementはデータの集合となるクラスである。クライアントはVisitorクラスに加え、すべてのElementを把握しているObjectStructureクラスを持つ。ObjectStructureクラスにあるVisitorを与えると、ObjectStructureはVisitor型の変数を受け取ると、すべてのElementに対して引数を渡す形でAccept関数を実行する。Elementは与えられたVisitorに対して自身のポインタを返し、具体的な処理はVisitorクラスで実装する。
実装:VisitorクラスはElementクラスから多くの情報を取得する。そのため、Elementクラスのカプセル化を弱めてしまう欠点がある。
23Visitor.jpg
https://github.com/AtsushiSakai/cpp/blob/master/DesignPattern/Visitor/Visitor.cpp

##その他
この本はデザインパターン初期の本であり、他にデザインパターンは書かれていなかったが後に誕生したデザインパターンが多数ある。
###Protocol Hierachyパターン
目的:多くのオブジェクトを1つのクラスにまとめたいが、派生クラスの持つ関数が独立しており、基底クラスに空の関数を実装しなければならない かつ派生クラスが今後多数発生すると考えられるような状況で基底クラスを簡潔にするため用いられる
大規模C++ソフトウェアデザインを参考
https://qiita.com/shigural/private/62b27adfff3089bdac78

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?