【GoF】23種類のデザインパターンとは?Swiftでよく使う活用例
この記事からわかること
- GoFのデザインパターンとは?
- 23種類の概要と違い
- Swift(iOS)で活用されているパターンは?
- シングルトンやDelegate、Observerの実例
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
アプリケーションなどのソフトウェア開発における設計知識として「GoF」の「デザインパターン」についてまとめて行きます。
GoFのデザインパターンとは?
GoFのデザインパターンとはオブジェクト指向ソフトウェアの設計に関する知見やノウハウに再利用性しやすいようにまとめたものです。
これは1994年にErich Gamma、Richard Helm、Ralph Johnson、John Vlissidesの4人の著者によって出版された、「Design Patterns: Elements of Reusable Object-Oriented Software」という書籍に記載された23種類のソフトウェアデザインパターンとして初めて世の中に公開されました。その4人のことをまとめてGoF(Gang of Four)と呼ばれています。
デザインパターンはオブジェクト指向型のプログラミング言語を使用したソフトウェア開発において基本的な考え方や設計原則を表現したものです。そのため今でもJavaやC#、Python、Ruby、Swiftなど数多くのオブジェクト指向型のプログラミング言語で活用されています。
しかし言語やプラットフォームによってデザインパターンの具体的な実装方法や適用範囲が異なる場合が多いので特定の言語やプラットフォームに依存せず、一般的な設計原則を理解し、柔軟な設計を行うことが重要です。
23種類のデザインパターン
ざっと23種類存在するデザインパターンを見てみましょう。これらは大きく分けて「生成に関するパターン」、「構造に関するパターン」、「振る舞いに関するパターン」の3つのカテゴリに分かれています。
生成に関するパターン
デザインパターン名 | 概要 |
---|---|
Abstract Factory | 関連する複数のオブジェクト群を作成する抽象ファクトリを定義し、実際の作成は具象ファクトリで行う。 |
Builder | 複雑なオブジェクトを生成するために、生成過程を分解し、一つずつオブジェクトを生成するビルダーを使用する。 |
Factory Method | オブジェクトを生成するための抽象ファクトリを定義し、具象ファクトリを実装することで、オブジェクトの生成方法をカプセル化する。 |
Prototype | クラスのインスタンスを使用して、新しいオブジェクトを複製することで生成を行う。 |
Singleton | システム内で唯一のインスタンスを保証することで、グローバルなオブジェクトの生成を行う。 |
構造に関するパターン
デザインパターン名 | 概要 |
---|---|
Adapter | 互換性のないオブジェクト間でインターフェースを変換するためのアダプタを作成する。 |
Bridge | 抽象的な概念と具体的な実装を分離することで、柔軟な構造を作成する。 |
Composite | オブジェクトをツリー構造で階層的に組み合わせ、単一のオブジェクトとして扱えるようにする。 |
Decorator | オブジェクトに対して機能を追加するためのデコレータを作成する。 |
Facade | 複数のオブジェクトを一つの単純なインターフェースにまとめ、システムを簡略化する。 |
Flyweight | 重複して生成されるオブジェクトを共有して使用することで、メモリ使用量を削減する。 |
Proxy | オブジェクトに対するアクセスを制御するためのプロキシを作成する。 |
振る舞いに関するパターン
デザインパターン名 | 概要 |
---|---|
Chain of Responsibility | 複数のオブジェクトをチェーン状に組み合わせ、一つのオブジェクトから他のオブジェクトに順次処理を渡す。 |
Command | 要求をオブジェクトとしてカプセル化し、それらを操作することで、アンドゥ、リドゥなどの操作を実現する。 |
Interpreter | 文法規則を定義し、それに基づいて入力を解釈するためのインタプリタを作成する。 |
Iterator | オブジェクトの要素に順番にアクセスするためのイテレータを作成する。 |
Mediator | 複数のオブジェクト間で中央的な仲介役を持ち、相互作用を行うようにする。 |
Memento | オブジェクトの状態を保存し、必要に応じてその状態を復元する。 |
Observer | オブジェクトの状態変化を監視し、状態が変化した場合に依存オブジェクトに通知する。 |
State | オブジェクトの状態に応じて振る舞いを変化させることで、柔軟な振る舞いを実現する。 |
Strategy | アルゴリズムの集合を定義し、必要に応じてアルゴリズムを切り替えることで、柔軟な振る舞いを実現する。 |
Template Method | アルゴリズムの骨子を定義し、具体的な処理をサブクラスで実装することで、柔軟な振る舞いを実現する。 |
Visitor | 複数のクラスを訪問する処理を一つのクラスにまとめることで、新しい操作を追加しやすくする。 |
Swiftの設計で見るデザインパターン
Swiftでもデザインパターンがさまざまな箇所で活用されています。Swiftでの実例を見ながらよく使われているパターンの概要を整理しておきます。
Singletonパターン
Singleton(シングルトン)パターンはクラスインスタンスを1つしか生成しないデザインパターンです。これによりアプリ全体で共通したデータを扱うことができるようになっています。
SwiftではUIApplication
やUserDefaults
などでシングルトンインスタンスが活用されています。実際にはクラスのプロパティに自身のインスタンスを格納し、そのプロパティを常に参照することで同じインスタンスを保証させます。
UIApplication.shared
UserDefaults.standard
なのでシングルトンは簡単にオリジナルクラスに組み込むことが可能です。
class UserModel {
// シングルトンとなるようにsharedプロパティを定義
public var shared = UserModel()
}
MVCパターン
アーキテクチャとして知られるMVCもデザインパターンの1種です。プログラムの役割をView、Controller、Modelの3つに分割して設計するパターンであり、SwiftにおいてはUIKitフレームワークがMVCアーキテクチャに基づいているようです。
おすすめ記事:Swift(UIKit)のMVCアーキテクチャーとは?役割と構造まとめ
Delegateパターン
Delegate(デリゲート)パターンとは日本語で「委任/委譲」を意味する名前の通り、処理を委譲するためのデザインパターンです。 処理の委譲はオブジェクト間で行われます。SwiftにおけるDelegateの詳細は以下の記事を参考にしてください。
おすすめ記事:【Swift】delegate(デリゲート)とは?使い方とメリット
SwiftではApp Delegate
やUITableViewDelegate
などがDelegateパターンに倣った処理の委任が組み込まれています。
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
}
}
Observerパターン
Observer(オブザーバー)パターンは日本語で「観測」を意味する通り、オブジェクトの状態を観測し、それに応じてオブジェクトを更新するデザインパターンです。対象となる2つのオブジェクトがあり「観測される側(Subject)」と「観測する側(Observer)」に分かれます。(Subjectは被写体といった意味です)
SwiftではNotificationCenter
やKVO(Key-Value Observing)
を利用してオブジェクトの状態変化を監視することができます。またRXSwiftなどでも活用されています。
おすすめ記事:【GoF】Observerパターンとは?Publish-Subscribeパターンとの違い
Factory Methodパターン
Factory Methodパターンはオブジェクトの生成を担当するFactoryクラスを介して、オブジェクトの生成を行うデザインパターンです。
SwiftではUIKitにおけるViewの生成(UIViewクラスのサブクラスのインスタンス化)にFactory Methodが使われています。
おすすめ記事:【Swift/UIKit】UIViewクラスとは?使い方やプロパティまとめ
// UIViewクラスはインスタンス化時にサブクラスのインスタンスを生成するためのファクトリメソッドとしてinit(frame:)メソッドを提供している
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。