Menu
Coddy logo textTech

デザインパターン入門

CoddyのC++ジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 90/104。

Design patternsは、ソフトウェアの設計で生じる一般的な問題に対する、実証済みで再利用可能な解決策です。直接コピーして使うコードではなく、特定の課題を洗練された方法で解決するために、クラスとオブジェクトをどのように構成するかを示すテンプレートや設計図です。

この概念は「Gang of Four」(GoF)が1994年の著書で広めたもので、その中では23の基本的なパターンが体系化されています。これらのパターンは通常、次の3つのカテゴリに分類されます。

カテゴリ 目的
Creational Object の creation メカニズム Singleton、Factory、Builder
Structural Class と object の composition Adapter、Decorator、Composite
Behavioral Object の interaction と責任 Observer、Strategy、Command

なぜ design patterns を学ぶのでしょうか。design patterns は開発者間で共有される語彙を提供します。「ここでは Factory を使う」と言うだけで、複雑な考えをすぐに伝えられます。また、解決策を一から作り直すことを避け、コードをより柔軟で保守しやすくするのにも役立ちます。

C++では、design patternsはすでに学んだOOPの機能、つまり継承、ポリモーフィズム、抽象クラス、テンプレートを活用します。これからのレッスンでは、いくつかの重要なpatternsを実装し、それぞれがどのような場合に適したツールなのかを理解していきます。

challenge icon

チャレンジ

簡単

3つのデザインパターンカテゴリについての理解を示す、シンプルなパターンクラシファイアを構築しましょう。パターン名を受け取り、それが属するカテゴリ(Creational、Structural、または Behavioral)を、そのカテゴリの目的の簡単な説明とともに特定するシステムを作成します。

コードを3つのファイルに分けて整理します。

  • PatternCategory.h:デザインパターンカテゴリを表す、PatternCategoryという名前の抽象基底クラスを定義します。このクラスには次のものを含めます。
    • カテゴリ名を文字列として返す純粋仮想メソッド getName()
    • このカテゴリに属するパターンが何をするものかの説明を返す純粋仮想メソッド getPurpose()
    • 仮想デストラクタ

    次に、PatternCategoryを継承する3つの派生クラスを作成します。

    • CreationalCategory:名前として "Creational"、目的として "Object creation mechanisms" を返します
    • StructuralCategory:名前として "Structural"、目的として "Class and object composition" を返します
    • BehavioralCategory:名前として "Behavioral"、目的として "Object interaction and responsibility" を返します
  • PatternClassifier.h:指定されたパターンがどのカテゴリに属するかを特定できる PatternClassifierクラスを作成します。

    クラシファイアには、パターン名(文字列)を受け取り、適切な PatternCategory へのポインタを返す classify メソッドを用意します。メモリ管理にはスマートポインタ(std::unique_ptr)を使用してください。

    クラシファイアは、次のパターンを認識する必要があります。

    • Creational:SingletonFactoryBuilder
    • Structural:AdapterDecoratorComposite
    • Behavioral:ObserverStrategyCommand

    パターン名が認識されない場合は、nullptrを返します。

  • main.cpp:1つの入力、つまりデザインパターンの名前を読み取ります。

    PatternClassifierを作成し、それを使用して入力されたパターンを分類します。パターンが認識された場合は、次を出力します。

    [PatternName] is a [CategoryName] pattern
    Purpose: [CategoryPurpose]

    パターンが認識されない場合は、次を出力します。

    Unknown pattern: [PatternName]

たとえば、入力が Singleton の場合:

Singleton is a Creational pattern
Purpose: Object creation mechanisms

入力が Observer の場合:

Observer is a Behavioral pattern
Purpose: Object interaction and responsibility

入力が Proxy の場合:

Unknown pattern: Proxy

このチャレンジでは、継承、ポリモーフィズム、スマートポインタを実践しながら、デザインパターンの3つのカテゴリについての理解を深めます。これらはすべて、すでに習得した概念です。複数ファイルによる構成は、実際のプロジェクトで関連するクラスを整理する方法を反映しています。

自分で試してみよう

#include <iostream>
#include <string>
#include "PatternClassifier.h"

int main() {
    // パターン名を読み取る
    std::string patternName;
    std::cin >> patternName;
    
    // TODO: PatternClassifier のインスタンスを作成する
    
    // TODO: 分類器を使用して入力パターンを分類する
    
    // TODO: パターンが認識された場合、以下を出力する:
    // "[PatternName] is a [CategoryName] pattern"
    // "Purpose: [CategoryPurpose]"
    
    // TODO: パターンが認識されない場合 (nullptr)、以下を出力する:
    // "Unknown pattern: [PatternName]"
    
    return 0;
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: C++オンラインコンパイラ