【保存版】GoFデザインパターン一覧|全23種類の目的とPython実装例

【保存版】GoFデザインパターン一覧|全23種類の目的とPython実装例

PR Amazonのアソシエイトとして、ITナレッジライフは適格販売により収入を得ています。

記事の文字数:3,487

オブジェクト指向設計の基本となる「GoFデザインパターン」全23種類の一覧と、それぞれの目的・特徴をわかりやすく解説します。Pythonでの実装例も交えながら、どのような課題を解決できるのかを学びましょう。

Pythonユーザにお勧めの本 ↗

初心者向け

1週間でPythonの基礎が学べる本

難易度
実用性
読みやすさ

「絶対に挫折させない」という著者の強い意志を感じる、プログラミングの「最初の1冊」としておすすめできる良書です。

人気

スッキリわかるPython入門 第2版 スッキリわかるシリーズ

難易度
実用性
読みやすさ

対話形式でスラスラ読める。複雑な概念もキャラクターが分かりやすく解説してくれます。

独習Python

難易度
実用性
網羅性

言語仕様を深く解説。なんとなく書ける状態から、自信を持って書ける状態へ引き上げてくれます。

Python1年生 第2版 体験してわかる!会話でまなべる!プログラミングのしくみ

難易度
実用性
読みやすさ

イラスト中心で、プログラミングの楽しさを教えてくれる。ワクワクしながら学べる入門書です。

ソフトウェア開発において、オブジェクト指向ソフトウェアで繰り返し現れる設計上の問題と、その解決策を整理・体系化したものがデザインパターンです。中でも最も有名で基本となるのが、4人の著者(Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides)がまとめた「GoFデザインパターン」です。

本記事では、GoFデザインパターンの全23種類を一覧にまとめ、それぞれの目的や特徴、さらに代表的なパターンのPythonPython [パイソン]汎用プログラミング言語実装例を解説します。

GoFデザインパターンとは?

GoF(Gang of Four)デザインパターンは、1994年に出版された書籍『Design Patterns: Elements of Reusable Object-Oriented Software』で紹介された23種類の設計パターンのことです。

これらのパターンは、オブジェクト指向プログラミングにおける再利用性や拡張性などを考慮した設計の「定石」として、現代のソフトウェア開発にも大きな影響を与えています。また、さまざまなフレームワークやライブラリの設計を理解するうえでも役立ちます。

GoFデザインパターンは、その目的に応じて以下の3つのカテゴリに分類されます。

  1. 生成(Creational)パターン(5種類):オブジェクトの生成に関するパターン
  2. 構造(Structural)パターン(7種類):クラスやオブジェクトの組み合わせに関するパターン
  3. 振る舞い(Behavioral)パターン(11種類):オブジェクト間の責任や通信に関するパターン

それでは、各カテゴリごとにパターンの一覧を見ていきましょう。

1. 生成(Creational)パターンの一覧

オブジェクトの生成プロセスを抽象化し、システムの柔軟性を高めるためのパターンです。

パターン名目的・特徴
Singleton(シングルトン)クラスのインスタンスが1つだけになることを保証し、
そのインスタンスへのグローバルなアクセス手段を提供する。
Factory Method(ファクトリーメソッド)インスタンスの生成をサブクラスに委譲し、
生成するクラスを柔軟に変更できるようにする。
Abstract Factory(抽象ファクトリー)関連する一連のオブジェクト群を、
その具象クラスを指定せずに生成するインターフェースを提供する。
Builder(ビルダー)複雑なオブジェクトの生成過程を分離し、
同じ生成過程で異なる表現のオブジェクトを構築できるようにする。
Prototypeprototype [プロトタイプ]動作確認や検証のために作成される試作品(プロトタイプ)典型的なインスタンス(プロトタイプ)をコピーすることで、
新しいオブジェクトを生成する。

【実装例】Singleton パターン(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(同じインスタンスを参照している)

補足: 上記のSingleton実装はパターンの概念を説明するための簡易的なものであり、マルチスレッド環境ではスレッドセーフではありません。実際のマルチスレッド環境で利用する場合は、ロック(排他制御)などの仕組みを併用する必要があります。

2. 構造(Structural)パターンの一覧

クラスやオブジェクトを組み合わせて、より大きな構造を作るためのパターンです。

パターン名目的・特徴
Adapter(アダプター)互換性のないインターフェースを変換し、
既存のクラスを修正せずに利用できるようにする。
Bridge(ブリッジ)「機能の階層」と「実装の階層」を分離し、
それぞれを独立して拡張できるようにする。
Composite(コンポジット)部分と全体を同じインターフェースで扱えるようにし、
木構造を表現する。
Decorator(デコレーター)オブジェクトに動的に新しい責任(機能)を追加する。
サブクラス化の代替手段。
Facade(ファサード)複数の複雑なサブシステムに対する
シンプルな窓口(インターフェース)を提供する。
Flyweight(フライウェイト)多数の細かいオブジェクトを効率的に共有し、
メモリ使用量を削減する。
Proxyproxy [プロキシ]クライアントとサーバーの間に立って通信を中継するサーバー(プロキシ)オブジェクトへのアクセスを制御するための代理(プロキシ)オブジェクトを提供する。

【実装例】Adapter パターン(Python)

# 既存のクラス(インターフェースが合わない)
class OldSystem:
def old_method(self):
return "古いシステムでの処理"
# アダプタークラス
class Adapter:
def __init__(self, old_system):
self.old_system = old_system
def new_method(self):
# 古いメソッドを新しいインターフェースに合わせて呼び出す
return self.old_system.old_method()
# 利用側
old_sys = OldSystem()
adapter = Adapter(old_sys)
print(adapter.new_method()) # "古いシステムでの処理"

補足: GoFの原著において、Adapterパターンには多重継承を用いる「クラスアダプタ」と、上記のように委譲(インスタンスの保持)を用いる「オブジェクトアダプタ」の2種類が言及されています。このコード例はオブジェクトアダプタの実装例となります。

3. 振る舞い(Behavioral)パターンの一覧

オブジェクト間の責任の割り当てや、アルゴリズムの制御に関するパターンです。

パターン名目的・特徴
Observer(オブザーバー)状態の変化を監視し、変化があった際に依存するオブジェクトに自動的に通知する。
Strategy(ストラテジー)アルゴリズムをカプセル化し、実行時に動的に切り替えられるようにする。
State(ステート)オブジェクトの内部状態が変化したときに、その振る舞いを変更できるようにする。
Command(コマンド)要求(操作)をオブジェクトとしてカプセル化し、取り消し(Undo)やキューイングを可能にする。
Chain of Responsibility(責任連鎖)複数のオブジェクトをチェーン状に繋ぎ、要求を処理できるオブジェクトが見つかるまで順に渡していく。
Iterator(イテレータ)コレクションの内部表現を公開することなく、要素に順番にアクセスする方法を提供する。
Mediator(メディエーター)オブジェクト間の複雑な通信を中央の仲介者(メディエーター)に集約し、結合度を下げる。
Memento(メメント)カプセル化を破壊せずに、オブジェクトの過去の状態を保存・復元できるようにする。
Template Method(テンプレートメソッド)処理の骨組みをスーパークラスで定義し、具体的な処理の一部をサブクラスに委譲する。
Visitor(ビジター)データ構造を変更せずに、要素に対して新しい操作を追加できるようにする。
Interpreter(インタープリタ)特定の言語や文法の規則を定義し、それを解釈して実行する仕組みを提供する。

【実装例】Strategy パターン(Python)

from abc import ABC, abstractmethod
# 戦略のインターフェース
class DiscountStrategy(ABC):
@abstractmethod
def calculate(self, price: int) -> int:
pass
# 具象戦略1:割引なし
class NoDiscount(DiscountStrategy):
def calculate(self, price: int) -> int:
return price
# 具象戦略2:20%オフ
class TwentyPercentOff(DiscountStrategy):
def calculate(self, price: int) -> int:
return int(price * 0.8)
# コンテキスト(利用側)
class ShoppingCart:
def __init__(self, strategy: DiscountStrategy):
self.strategy = strategy
def checkout(self, price: int):
final_price = self.strategy.calculate(price)
print(f"最終価格は {final_price} 円です。")
# 実行時に戦略を切り替える
cart1 = ShoppingCart(NoDiscount())
cart1.checkout(1000) # 最終価格は 1000 円です。
cart2 = ShoppingCart(TwentyPercentOff())
cart2.checkout(1000) # 最終価格は 800 円です。

💡 コラム:現代のプログラミング事情とデザインパターン

GoFデザインパターンが提唱された1994年当時から時代は進み、現代のソフトウェア開発においてはいくつかのパターンに対する考え方が変化しています。

1. Singletonは「アンチパターン」になりつつある?

前述のSingletonパターンですが、近年では 「グローバルな状態を持つためテスト容易性が低下し、コードの柔軟性を奪う」 として、アンチパターンとみなされることが増えています。 現代のWeb開発やアプリケーション開発では、自前でSingletonクラスを実装するのではなく、DI(依存性の注入)コンテナのスコープ管理(SpringやDaggerなど)を利用して、インスタンスを1つに制限するアプローチが主流となっています。

2. モダン言語(Pythonなど)によるパターンの不要化・簡略化

Pythonなどの動的型付け言語や、関数を第一級オブジェクトとして扱える(クロージャや高階関数をサポートする)モダンな言語においては、GoFのいくつかのパターンが言語機能自体に吸収されています。

  • Commandパターン:わざわざクラスを定義しなくても、「高階関数」や「クロージャ(Pythonの関数オブジェクト)」を渡すだけでシンプルに代替できます。
  • Iteratorパターン:Pythonのジェネレータ(yield)や、言語標準のイテレータ構文(for ... in ...)などに完全に吸収されています。

Python等でデザインパターンを学ぶ際は、**「このパターンは言語の標準機能でよりシンプルに書けないか?」**という視点を持つと、より実用的な設計スキルが身につきます。

まとめ

本記事では、GoFデザインパターンの全23種類を一覧で紹介しました。

デザインパターンは「必ず使わなければならないもの」ではありませんが、設計の引き出しとして知っておくことで、開発者間でのコミュニケーション(共通言語)保守性の高いコード設計に大きく役立ちます。

まずは「Singleton」「Factory Method」「Observer」など、代表的なパターンから学び、実際のプロジェクトに適用できそうな場面を探してみることをおすすめします。


以上で本記事の解説を終わります。
よいITライフを!
ITナレッジライフ 運営者
この記事を書いた人

Z (ITナレッジライフ)

現役のITエンジニア。Linux、プログラミング、IT用語など、日々の業務で得た「痒いところに手が届く」技術情報を発信しています。

プロフィールと編集ポリシーを見る

Pythonユーザにお勧めの本 ↗

初心者向け

1週間でPythonの基礎が学べる本

難易度
実用性
読みやすさ

「絶対に挫折させない」という著者の強い意志を感じる、プログラミングの「最初の1冊」としておすすめできる良書です。

人気記事


記事を評価

Thanks!
目次
Scroll to Top