デザインパターン
GoFのデザインパターンはOOP(オブジェクト指向言語向け)
オブジェクト指向プログラミング(OOP)と関数型プログラミング(FP)では、異なるデザインパターンが存在します。これらのパターンは、それぞれのプログラミングパラダイムの特性や哲学に基づいています。
オブジェクト指向プログラミングのデザインパターン
オブジェクト指向プログラミングでは、クラスやオブジェ クトを通じてデータとそのデータを操作するメソッドを組み合わせることに焦点を当てています。OOPのデザインパターンは、ソフトウェア設計における一般的な問題に対する再利用可能な解決策を提供します。有名なOOPのデザインパターンには、以下のようなものがあります:
ファクトリーメソッド(Factory Method): オブジェクトの作成をサブクラスに委ねることで、クライアントコードが具体的なクラスに依存することなくオブジェクトを生成できるようにするパターンです。 シングルトン(Singleton): あるクラスのインスタンスがプログラム内に1つしか存在しないことを保証するパターンです。 ストラテジー(Strategy): アルゴリズムのファミリーを定義し、それらを相互に交換可能にすることで、アルゴリズムをクライアントの使用によって動的に変更できるようにするパターンです。 オブザーバー(Observer): オブジェクト間の依存関係を設定することで、あるオブジェクトの状態が変わったときに、依存しているすべてのオブジェクトに自動的に通知が行われるようにするパターンです。 関数型プログラミングのデザインパターン 関数型プログラミングでは、不変性(Immutable)、副作用のない関数(Pure Functions)、高階関数(Higher-order Functions)などの概念を使用して問題を解決します。FPのデザインパターンは、これらの概念を活用して、より宣言的な(Declarative)、副作用のないコードを書くための方法を提供します。FPのパターンには以下のようなものがあります:
モナド(Monad): 副作用を扱うための一貫した方法を提供し、チェーン可能な操作を通じて値を変換するパターンです。 ファンクター(Functor): 値をラップし、その値に関数を適用する方法を提供するパターンです。 カリー化(Currying): 複数の引数を取る関数を、一度に1つの引数を取る関数のシリーズに変換するパターンです。 コンポジション(Composition): 複数の関数を組み合わせて、新しい関数を作るパターンです。
実のところデザインパターンやオブジェクト指向のテクニックのアレコレは、突き詰めると具象クラスの代わりにインタフェースを使ったり、抽象クラスを使ったりすることが基本なのです。 従って「具象クラスを書かずにインスタンスを生成する」ためにFactory Methodパターンが実際何をするかと言うと、「具象クラスの代わりにインタフェースや抽象クラスを使ってインスタンス生成する」といった事を行うのです。
これらは、特定の問題を解決するための再利用可能なソリューションです。Gang of Four (GoF) によって23のクラシックなデザインパターンが紹介されました。
-
Creational Patterns (生成パターン):
- Singleton
- Factory Method
- Abstract Factory
- Prototype
- Builder
-
Structural Patterns (構造パターン):
- Adapter
- Bridge
- Composite
- Decorator
- Facade
- Flyweight
- Proxy
-
Behavioral Patterns (振る舞いパターン):
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
デザインパターンとは
ソフトウェア開発におけるデザインパターンまたは設計パターンとは、過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、名前をつけ再利用しやすいように特定の規約にしたがってカタログ化したもの
※GoFのデザインパターンと呼ぶこともある。
デザインパターンは、再利用可能なソフトウェア設計の解決策
デザインパターンは主に3つのカテゴリーに分類される
- Creational(生成)
- Structural(構造)
- Behavioral(振る舞い)
デザインパターン一覧
現在は使用されているのか
結論としては、GoFのデザインパターンは綺麗にまとまっていて勉強にはなるが、 複雑すぎて普段は使わないというのが実態。
(一昔前に出た結論ではあるが)
TypeScriptでは_
JavaScriptが関数を変数として扱える第一級関数言語であることもGoFのデザインパターンを使わなくなる理由のひとつである可能性。
デザインパターン一覧
23種類をさらに3つに分けることができる
生成に関するパターン
Abstract Factory
関連する部品を組み合わせて製品を作る
Builder
複雑なインスタンスを組み立てる
Factory Method
インスタンス生成をサブクラスにまかせる
Prototype
コピーしてインスタンスを作る
Singleton
たったひとつのインスタンス
構造に関するパターン
Adapter
一皮被せて再利用
インターフェースが一致しないクラスを再利用する
Bridge
機能の階層と実装の改装を分ける
Composite
容器と中身の同一視
Decorator
飾り枠と中身の同一視
Facade
シンプルな窓口
Flyweight
同じものを共有してむだをなくす
Proxy
必要になってから作る
振る舞いに関するパターン
Chain of Responsibility
責任のたらい回し
Command
命令をクラスにする
Interpreter
文法規則をクラスで表現する
Iterator
1つ1つ数え上げる
Mediator
相手は相談役1人だけ
Memento
状態を保存する
Observer
状態の変化を通知する
State
状態をクラスとして表現する
Strategy
アルゴリズムをごっそり切 り替える
Template Method
具体的な処理をサブクラスに任せる
Visitor
構造を渡り歩きながら仕事をする
デザインパターンとDI
依存性注入 DI : Dependency Injection
あるオブジェクトを利用する時にメソッドの引数などでオブジェクトを受け取るようにし依存関係は外部から任意に指定、変更できるようにすること。
Aを呼び出す側がB(に相当するオブジェクト)を与えて利用させる。これにより、AとBの依存関係は外部から任意に指定、変更できるようになり、Bの代わりに同じインターフェースを実装したB'を与えたり、Bのように振る舞うモックを与えてAのみを対象とする単体テストを行ったりできる。
デザインパターンとドメイン駆動設計(DDD)の違い
デザインパターンとドメイン駆動設計(DDD)は、ソフトウェア設計の異なる側面を扱っていますが、一部の概念やアプローチは重なる部分もあります。
-
デザインパターン: デザインパターンは、特定の一般的な設計上の問題を解決するための再利用可能なソリューションです。これらのパターンは、オブジェクトの生成、構造、振る舞いに焦点を当てています。デザインパターンは具体的な技術やドメインに依存せず、多くの異なるコンテキストで再利用できる解決策です。
-
ドメイン駆動設計(DDD): DDDは、複雑なビジネスロジックやビジネスプロセスを扱うソフトウェアの設計アプローチです。DDDは、ドメインエキスパートと開発者が共同でビジネスドメインを深く理解し、その知識をソフトウェアの設計に反映させることを重視しています。DDDには、エンティティ、値オブジェクト、アグリゲート、レポジトリなど、特定のドメインモデリングのパターンが含まれます。
要するに、デザインパターンは設計の「方法」に焦点を当てたもので、DDDはビジネスロジックとソフトウェア設計の「結合」に焦点を当てたアプローチです。DDDは、ビジネスの要件とソフトウェアの設計が密接に結びついている複雑なドメインでとくに有効です。
両者は異なるコンセプトではありますが、DDDのプロジェクトで一般的なデザインパターンが利用されることはよくあります。また、DDD自体も、エンティティやレポジトリなどのパターンを定義しているので、ある意味で特定のドメインに特化したデザインパターン集とも言えます。