34
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

デザインパターンの学習

Last updated at Posted at 2017-12-03

#はじめに
各デザインパターンの要点をまとめます。
自分用のメモとなります。
C#を元に考えています。

#1.Iterator
##Iteratorパターンとは
オブジェクトの操作手順をオブジェクト自身に持たせ、その種類や実装に依存しない、統一的なデータへのアクセス方法を提供する。

現在では言語組み込みとなっていることが多いため、使用機会は少ない(C#ではIEnumerable<T>が存在する、使用するのであればデータベース関連などの集合的なクラスを作成した場合)。

##クラス図
500px-Iterator_UML_class_diagram.png
https://ja.wikipedia.org/wiki/Iterator_パターン

#2. Adapter
##Adapterパターンとは
インターフェースの異なるクラスに対して、ラッパークラスを作成することにより、既存のクラスに手を加えずにインターフェースの統一を行う(目的のクラスに対して、既存クラスがそのまま利用できない場合に、クラス間の相違を適合させる)。

実装方法は継承、委譲(コンポジション)の二つが存在する。

##クラス図
継承
500px-Adapter_using_inheritance_UML_class_diagram.png
https://ja.wikipedia.org/wiki/Adapter_パターン

委譲(コンポジション)
500px-Adapter_using_delegation_UML_class_diagram.png
https://ja.wikipedia.org/wiki/Adapter_パターン

#3. TemplateMethod
##TemplateMethodパターンとは
スーパークラスにおいて、必要な処理(抽象・仮想)とその呼び出しを定義し、サブクラスにおいて、処理の詳細を実装することにより、テンプレートに沿った処理の実装を可能にする。

抽象クラスの一般的な使い方であり、システムのフレームワークを構築する際に使用されることが多い。

##クラス図
450px-Template_Method_UML_class_diagram.png
https://ja.wikipedia.org/wiki/Template_Method_パターン

#4. FacotoryMethod
##FacotoryMethodパターンとは
オブジェクトの生成手順をパターン化したものであり、インスタンス生成の呼び出しをスーパークラスに定義し、インスタンスの生成、具体的な実装をサブクラスで行う(TemplateMethodのインスタンス版)。インスタンスの生成をメソッド呼び出しに代えることにより、インスタンスの生成と処理を分離する。

生成対象となるProductクラスとその生成を行うFactoryクラスをスーパークラスとして定義することで、サブクラスであるConcreteFactoryの入れ替えにより、自由にConcreteProductを使用することができる(生成するクラスの種類や生成手順が追加、変更されてもFactoryの修正のみで済むため、保守性が高まる)。

インスタンスの種類が将来的に増える場合、サブクラスを指定せずにインスタンスを生成したい場合、対となるオブジェクトを関連するオブジェクトに生成させたい場合などに使用する。

##クラス図
500px-Factory_Method_UML_class_diagram.png
https://ja.wikipedia.org/wiki/Factory_Method_パターン

#5. Singleton
##Singletonパターンとは
複数のインスタンスを生成する必要のないクラスに対し、唯一のインスタンスのみを生成可能とすることを保証する。

privateなコンストラクタ、唯一のインスタンスを格納するprivateな静的変数、唯一のインスタンスを取得するpublicな静的メソッドにより構成される。

起動時の設定クラスやログ出力などシステムにおいて同一の値を参照したい場合、インスタンス生成にコストがかかる場合などに用いる。

※C#の静的クラスのとの違い
静的クラスはコード量が少なくなる。
シングルトンは継承、仮想、インターフェース、ポリモーフィズムを使用しオブジェクト指向なプログラミングが行える。

※静的変数とは
クラス変数、static変数のことであり、クラスのすべてのインスタンスに共有される。

##クラス図
300px-Singleton_UML_class_diagram.png
https://ja.wikipedia.org/wiki/Singleton_パターン

#6. Prototype
##Prototypeパターンとは
原型(プロトタイプ)となるインスタンスをコピーして、新しいインスタンスを作成する。

複雑な処理を経て生成されるインスタンスを複数使用したい場合、生成直後のインスタンスを保持しておきたい場合に使用する。また、テンプレートとなる複数のインスタンスを、状況に応じて生成したい場合などにも使用する(Keeper(管理者)となるクラスを用意し、必要となる原型(プロトタイプ)をmapで保持しておく)。

※コピーの深さに注意する必要がある(ShallowCopyとDeepCopy)。

##クラス図
600px-Prototype_UML.png
https://ja.wikipedia.org/wiki/Prototype_パターン

#7. Builder
##Builderパターンとは
オブジェクトの生成過程を抽象化することによって、複雑なオブジェクトの構築方法をカプセル化し、動的なオブジェクトの生成を可能にする。

Client(依頼者)はDirector(監督者)に対して、任意のBuilder(建築者)(具象)を渡し、DirectorはBuileder(抽象)のインターフェースのみを使用し、Productを作成する。渡すBuilderを入れ替えることにより動的にProductを生成する。

##クラス図
700px-Builder_UML_class_diagram.png
https://ja.wikipedia.org/wiki/Builder_パターン

#8. AbstractFactory
##AbstractFactoryパターンとは
関連するインスタンス群をまとめて生成する方法を提供することにより、関連オブジェクトグループ単位での入れ替え、追加を容易にする。

FactoryMethodがオブジェクト生成の抽象化であるのに対して、AbstractFactoryは関連するオブジェクト群をまとめて生成する手順の抽象化を行う(工場の工場)。

##クラス図
650px-Abstract_Factory_UML_class_diagram.png
https://ja.wikipedia.org/wiki/Abstract_Factory_パターン

#9. Bridge
##Bridgeパターンとは
「機能のクラス階層」と「実装のクラス階層」を分離し、橋渡しを行うことにより、それぞれを独立して拡張できるようにする。
※「機能のクラス改装」とは、スーパークラスに新しい機能を追加しサブクラスを作成すること(継承による機能拡張)。「実装のクラス改装」とは、スーパークラス、またはインターフェースで定義された抽象メソッドをサブクラスにて実装すること。

例えば、抽象クラスAとその実装を行うクラスB、クラスCが存在する時、抽象クラスAの機能を拡張した抽象クラスA2を作成したい場合、その実装を行うクラスB2とクラスC2が必要となり、また、次に抽象クラスAの実装を行うクラスDを追加したい場合、抽象クラスA2に対してもその実装を行うクラスD2を追加する必要がある(必須ではないが多くの場合、そのようなケースとなる)。
つまり、「機能のクラス改装」と「実装のクラス階層」が結合されている場合、機能を拡張するごとにクラスの数が膨れ上がってしまう。このようなケースを回避するため、Bridgeパターンでは「機能のクラス改装」のスーパークラスが「実装のクラス改装」を集約することによりそれぞれを分離することができる(下記クラス図の集約部分が橋となる)。

##クラス図
Bridge_UML_class_diagram.png
https://ja.wikipedia.org/wiki/Bridge_パターン

#10. Strategy
##Strategyパターンとは
アルゴリズムのインターフェースを定め、委譲を用いることにより、アルゴリズムを動的に切り替える。

C#のデリゲートとの違いは、Strategyパターンはアルゴリズムをクラスで定義するため、状態を持つことができること。また、複数のメソッドが定義可能となること。

※Bridgeパターンとクラス図が類似するが、Bridgeパターンが構造に対するパターンであるのに対して、Strategyパターンは振る舞いに対するパターンである。

##クラス図
500px-StrategyPatternClassDiagram.png
https://ja.wikipedia.org/wiki/Strategy_パターン

#11. Composite
##Compositeパターンとは
枝と葉を同一に扱う(抽象化する)ことで、再帰的なツリー構造を実現する。
※再帰的な構造とはWindowsにおけるフォルダとファイルや、会社における部、課、班など。

##クラス図
360px-Composite_UML_class_diagram_(fixed).svg.png
https://ja.wikipedia.org/wiki/Composite_パターン

#12. Decorator
##Decoratorパターンとは
既存のオブジェクトを、委譲を用いてDecoratorオブジェクトによりラップすることで、既存に手を加えることなく、機能、振る舞いを動的に追加することを可能にする。
※同一のインターフェースを持つことで既存のオブジェクトとDecoratorオブジェクトを同一に扱うことが可能となる。

##クラス図
480px-Decorator_UML_class_diagram.png
https://ja.wikipedia.org/wiki/Decorator_パターン

#13. Visitor
##Visitorパターンとは
処理をデータ構造から分離することにより、データ構造に変更を加えることなく、処理の追加、拡張を可能にする。
※処理の追加、変更は容易となるが、データ構造の追加、変更は各Visitorクラスの修正が必要となるため、困難となる。

データ構造の独立性を高めることが目的であるため、Visitor、Elementで相互に処理を呼び出すダブルディスパッチを用いて実現する。

下記のクラス図ではVisitorクラスのVisitメソッドは一つだが、データ構造(ConcreteElement)の数だけVisitメソッドをオーバーロードして定義する。
※Visitメソッドは一つのクラスのメソッドではなく、データ構造との対となるメソッドとなる。

##クラス図
VisitorClassDiagram.png
https://ja.wikipedia.org/wiki/Visitor_パターン

#14. Chain of Responsibility
##Chain of Responsibilityパターンとは
複数のオブジェクトを鎖のように繋いで順次アクセスし、目的のオブジェクト(処理を実行するオブジェクト)を決定する。
要求側と処理側の結びつきを弱めることにより、処理の独立性を上げる。また、要求により必要となる処理を選択可能とする。

※柔軟性は上がるが、処理速度は下がるため、状況により使用の有無を判断する。

##クラス図
chainOfResponsibility3.gif
http://www.techscore.com/tech/DesignPattern/ChainOfResponsibility.html/

#15. Facade
##Facadeパターンとは
複数のクラス、複数のメソッドを使用して処理を実現する際に、窓口となる一つのAPIを提供することにより、使用手順やクラスの仕様把握などの、利用者側の実装負担を軽減する。また、外部との結合を疎にすることにより、部品としての再利用性を高める。

##クラス図
500px-Facade_UML_class_diagram.png
https://ja.wikipedia.org/wiki/Facade_パターン

#16. Mediator
##Mediatorパターンとは
複数のオブジェクト間で相互に通信する必要がある場合に、調停者となるオブジェクトを用意し、オブジェクト間での通信を調停者を通じて行わせることにより、結合の度合いを下げることを可能にする。
※処理を各オブジェクトに分散させず、調停者に集約することができる。

GUIアプリケーションにおける複雑なコントロール間の制御などに使用される。

##クラス図
mediator.png
http://www.techscore.com/tech/DesignPattern/Mediator.html/

#17. Observer
##Observerパターンとは
オブジェクトの状態の変化、イベントの発生などを観察者(Observer)に通知し、それに沿って処理を行う。GUIシステムなどで使用される。

観察対象(Subject)は自身の状態に変化があった場合、notifyメソッドを呼び出し、自身の保持する全てのObserverのupdateメソッドを呼び出す。updateメソッドの振る舞いにより、Observerパターンは以下の二つに分類される。

・Push型
Push型はupdateメソッドの引数に自身の状態を設定し、Observerに通知する。
状態の変化を直接知ることができるが、インターフェースが統一できない。
Subjectの状態が単純な場合に推奨される。

・Pull型
Pull型はupdateが呼び出された際に、ObserverからSubjectに対して状態を問い合わせる。
状態の変化に対して問い合わせが発生するが、インターフェースが統一される。
Subjectの状態が複雑な場合に推奨される。

##クラス図
Observer-pattern-class-diagram.png
https://ja.wikipedia.org/wiki/Observer_パターン

#18. Memento
##Mementoパターンとは
オブジェクトの状態のバックアップと復元を実現する(内部構造のカプセル化を崩さずに実現する)。
※Prototypeパターンなどのインスタンスのコピーも可能であるが、Mementoパターンでは必要となる時点の必要なデータのみのバックアップと復元を行うことを目的とする。

Originater(作成者)は自身のクラス内にMemento(記念品)クラスを持ち、Mementoに対して自身の状態をバックアップしたMementoを作成する機能、要求されたMementoから自身の状態を復元の機能を持つ(OriginaterとMementoはお互いに依存する。)。

CareTaker(世話人)は使用者の指示に従い、Originaterに対してMementoの作成要求とその保持(履歴を管理)、必要となる時点のMementoからの復元要求を行う。

※保持する状態は必要最小限、Mementoオブジェクトにはアクセスさせない。

##クラス図
memento2.gif
http://www.techscore.com/tech/DesignPattern/Memento.html/

#19. State
##Stateパターンとは
オブジェクトの状態によって振る舞いが変わる場合に、各状態に対応するクラスを作成し、それらを切り替えることにより、各振る舞いを表現する。
※条件分岐で管理することもできるが、状態の変更、追加、削除があった場合はすべてに修正を入れる必要があるため、保守性が低くなる。つまり、Stateパターンを使用することにより保守性が高まる。

##クラス図
state2.gif
http://www.techscore.com/tech/DesignPattern/State.html/

#20. FryWeight
##FryWeightパターンとは
同一のインスタンスを異なる箇所で使用する際に、一つのインスタンスを再利用することによりリソースを軽減することを目的とする。

使用者はFlyWeightFactoryを通じて、対象となるインスタンス(FryWeight)を取得する。その際に、インスタンスが未生成の場合は生成、保持(Map)、返却を行い、生成済みの場合は返却のみを行う。
※未生成、生成済みで異なる処理となるが、利用者はFlyWeightFactoryの内部構造を意識せずに使用することができる。
※FactoryクラスをSingletonとして実装することで複数のFactoryが生成されることを防ぐ。

また、対象となるインスタンスは各箇所で使用されることとなるため、適用のパターンとしては変更が加えられない不変なクラス(immutable)が適切となる。
※生成後に状態を変えることができないクラス

##クラス図
500px-Flyweight_UML_class_diagram.png
https://ja.wikipedia.org/wiki/Flyweight_パターン

#21. Proxy
##Proxyパターンとは
特定のオブジェクト(Subject)へのアクセスを、共通のインターフェースを持つ代理人(Proxy)を介して行わせる。
※共通のインターフェースを持つことにより、使用者が処理の実施者を意識する必要がない。

代理可能な処理をProxyで実施し、代理できない処理のみをコンポジションで保持したSubjectで実施することにより、Subjectへの負荷を軽減することを目的とする。
※Decoratorと類似するが、こちらは新しい機能の追加を目的とする。

##クラス図
proxy2.gif
http://www.techscore.com/tech/DesignPattern/Proxy.html/

#22. Command
##Commandパターンとは
命令をクラスとして表現することにより、オブジェクトに切り替えによって操作を切り替えることを可能にする。

利用者(Client)は命令(Command)に受信者(Receiver)をセットし、起動者(Invoker)への命令の格納と起動を行う。
※Receiverをインターフェースで定義することで、複数の受信者を作成することも可能。

用途として、Invokerにて完了した命令をスタック構造で保持することにより、作業履歴のアンドゥ、リドゥが実現できる。また、実行時間を持つ命令をキュー構造として保持することにより、残りの所要時間(プログレスバー)の算出が実現できる。

##クラス図
Command_Design_Pattern_Class_Diagram.png
https://ja.wikipedia.org/wiki/Command_パターン

#23. Interpreter
##Interpreterパターンとは
何らかのフォーマットを持った文書(事象)に対して、その文法規則をクラスで表現し、構文解析とその結果に基づく処理を実施することにより、特定の問題に最適化した解決方法を提供する。

##クラス図
interpreter4.gif
http://www.techscore.com/tech/DesignPattern/Interpreter.html/

##おわりに
一旦、終わりとなります。
余裕があれば修正、追記を行いたいと思います。

以上となります。

34
44
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
34
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?