GoF(Gang of Four)とは?ソフトウェア設計を支えるデザインパターンの基礎
1. はじめに
ソフトウェア開発において、「保守性が高く、再利用しやすい設計」 は重要なテーマです。
しかし、開発者が独自に設計を考えると、類似した問題に対して異なる解決策が生まれ、結果としてコードの一貫性が失われる ことがあります。
そこで役立つのが、GoF(Gang of Four) が提唱したデザインパターン です。
GoFのデザインパターンは、オブジェクト指向プログラミング(OOP)における「設計のベストプラクティス」 として、現在も多くの開発者に利用されています。
本記事では、まず GoFとは何か を詳しく解説し、
続いて 代表的なデザインパターン「Singleton」 の実装を複数のプログラミング言語で紹介します。
2. GoF(Gang of Four)とは?
2.1. GoFの概要
GoF(Gang of Four) は、1994年に出版された書籍
「Design Patterns: Elements of Reusable Object-Oriented Software」 の著者である4人のエンジニアの総称です。
著者名 | 主な功績 |
---|---|
Erich Gamma | JUnitの開発者、Eclipseの設計にも貢献 |
Richard Helm | IBMのソフトウェアエンジニア |
Ralph Johnson | オブジェクト指向設計の専門家 |
John Vlissides | デザインパターンの理論的基礎を確立 |
この書籍では、オブジェクト指向設計における23のデザインパターン を定義しており、
現在もソフトウェア設計の重要な指針として活用されています。
2.2. GoFのデザインパターンの分類
GoFは、デザインパターンを以下の3つのカテゴリに分類しています。
カテゴリ | 概要 | 代表的なパターン |
---|---|---|
生成パターン(Creational Patterns) | オブジェクトの生成を最適化する | Singleton, Factory Method, Builder, Prototype |
構造パターン(Structural Patterns) | クラスやオブジェクトの構造を最適化 | Adapter, Bridge, Decorator, Composite, Facade |
振る舞いパターン(Behavioral Patterns) | オブジェクト間の動作を管理 | Observer, Strategy, Template Method, Command |
この中でも、最も基本的で広く使われるパターンの1つが Singleton(シングルトン) です。
次章では、Singletonパターンの実装を複数の言語で解説 します。
Singletonパターン:唯一のインスタンスを保証するデザインパターン
3. Singletonパターンとは?
3.1. Singletonの概要
Singleton(シングルトン)パターン は、
「あるクラスのインスタンスを1つだけ生成し、それをグローバルにアクセスできるようにする」デザインパターンです。
✅ メリット - 唯一のインスタンスを保証 できる - グローバルアクセスを提供 できる - メモリ使用量を削減 し、不要なインスタンス生成を防ぐ
❌ デメリット - 依存関係が強くなりやすい(グローバル変数のような影響を持つ) - マルチスレッド環境での競合(適切な排他制御が必要)
4. 各言語でのSingletonパターンの実装
Singletonパターンは、言語によって異なる方法で実装されます。
ここでは、Java、Python、C++、Go での実装を紹介します。
4.1. Javaでの実装(スレッドセーフ対応版)
public class Singleton { private static volatile Singleton instance; private Singleton() {} // private コンストラクタ public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
✅ volatile
修飾子と synchronized
を使用し、スレッドセーフを確保
4.2. Pythonでの実装(クラス変数を利用)
class Singleton: _instance = None def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance # インスタンスの取得 obj1 = Singleton() obj2 = Singleton() print(obj1 is obj2) # True(同じインスタンス)
✅ __new__()
メソッドをオーバーライドし、唯一のインスタンスを保証
4.3. C++での実装(スレッドセーフ対応版)
#include <iostream> #include <mutex> class Singleton { private: static Singleton* instance; static std::mutex mutex; Singleton() {} public: static Singleton* getInstance() { std::lock_guard<std::mutex> lock(mutex); if (instance == nullptr) { instance = new Singleton(); } return instance; } }; // 静的メンバ変数の定義 Singleton* Singleton::instance = nullptr; std::mutex Singleton::mutex; int main() { Singleton* s1 = Singleton::getInstance(); Singleton* s2 = Singleton::getInstance(); std::cout << (s1 == s2) << std::endl; // 1(同じインスタンス) }
✅ std::mutex
を使用し、スレッドセーフなSingletonを実装
4.4. Goでの実装(sync.Onceを活用)
package main import ( "fmt" "sync" ) type Singleton struct{} var instance *Singleton var once sync.Once func GetInstance() *Singleton { once.Do(func() { instance = &Singleton{} }) return instance } func main() { s1 := GetInstance() s2 := GetInstance() fmt.Println(s1 == s2) // true(同じインスタンス) }
✅ sync.Once
を使用し、スレッドセーフなSingletonを実装
5. まとめ
項目 | 内容 |
---|---|
GoFとは? | 4人のエンジニアが提唱した23のデザインパターン |
分類 | 生成、構造、振る舞いの3つに分類 |
Singletonの目的 | 唯一のインスタンスを保証し、メモリ使用を最適化 |
実装言語 | Java, Python, C++, Go での実装を紹介 |
Singletonパターンは、多くのアプリケーションで使用される重要なデザインパターンです。
しかし、適用する際は「グローバル依存」や「スレッドセーフの確保」に注意する必要 があります。
📌 次回の記事:「GoFの他のデザインパターン(Factory, Builder)」もお楽しみに!
参考資料
バランスよく書かれている。
網羅的に書かれています。骨太。