ゲームBGMをすこれ

【コードあり】デコレーターパターンのc++版サンプルコード

WRITER
 

本ページはプロモーションが含まれています

スポンサードリンク



本ページはプロモーションが含まれています

この記事を書いている人 - WRITER -
ゲーム音楽をこよなく愛するものです。 このブログではゲーム音楽に関する記事や大学生活に関する記事、ブログに関する記事を紹介します。 超絶田舎の地方国立大学に通ってます。週1くらいで更新してるので暇なときに見に来てください。たまに面白い記事書いてます。彼女募集中!!←≪重要≫  
詳しいプロフィールはこちら

今回はデザインパターンのオブザーバーパターンのサンプルコードを作成しました。

記事の作成に当たってインプットには以下の書籍やサイトを使って勉強しました。

間違い等あればコメントしてもらえると対応します。

目次

デコレーターパターンの概要

デコレーターパターンは、デコレーターと呼ばれるラッパークラスを使用し、オブジェクトに新たに機能を追加することができるデザインパターンです。

元のクラスを変更することなく新たに機能を追加できる点がメリットです。

コンポーネント、具象コンポーネント、デコレーター、具象デコレータから構成され、それぞれ以下のような役割を持ちます。

  • コンポーネント : デコレーターとなるクラスやインターフェースを定義する。デコレーターと同じインターフェースを実装します。
  • 具象コンポーネント : コンポーネントの実装を提供するクラス。デコレーターがラップするオブジェクトの基本的な機能を実装します。
  • デコレーター : コンポーネントと同じインターフェースを持ち、そのコンポーネントをラップする。
  • 具象デコレーター : デコレーターの具体的な実装を提供するクラス。基本の機能に追加の機能を追加するために使用されます。

    構造はrefactoring.guruの図がわかりやすいのでそれ見て下さい。

    c++のサンプルコード

    今回はカフェでの注文をモデルにサンプルコードを作成してみました。

    コンポーネント(Beverage.h)

    デコレーターで使用する関数を定義します。

    #include <iostream>
    
    // コンポーネント(インターフェース)
    class Beverage {
    public:
        virtual std::string getDescription() const = 0;
        virtual double cost() const = 0;
        virtual ~Beverage() {}
    };

    デコレーター(CondimentDecorator.h)

    Beverageインターフェースを継承し、関数がコールされたときに代わりにメンバ変数で保持しているオブジェクト(具象コンポーネント)の関数をコールするようになっています。

    #include "Beverage.h"
    
    // デコレーター
    class CondimentDecorator : public Beverage {
    protected:
        Beverage* beverage;
    
    public:
        CondimentDecorator(Beverage* bev) : beverage(bev) {}
    
        std::string getDescription() const override {
            return beverage->getDescription();
        }
    
        double cost() const override {
            return beverage->cost();
        }
    };

    具象コンポーネント(Espresso.h)

    デコレーターによってコールされる関数を定義します。

    #include "Beverage.h"
    
    // 具象コンポーネント
    class Espresso : public Beverage {
    public:
        std::string getDescription() const override {
            return "Espresso";
        }
    
        double cost() const override {
            return 1.99;
        }
    };

    具象デコレーター(Milk.h, Syrup.h)

    具象デコレータは、具象コンポーネント(Espresso)をラップするために使用されます。そして、ラップされたオブジェクトを親クラスのコンストラクタに渡します。

    このようにすることで、具象コンポーネントのgetDescription関数がコールされたとき、EspressoのgetDscriptioonではなく、デコレーターのgetDescriptionがコールされるようになり、元々のEspressoのgetDescriptionは具象デコレータからコールされます。

    #include "CondimentDecorator.h"
    
    // 具象デコレーター - ミルク
    class Milk : public CondimentDecorator {
    public:
        Milk(Beverage* bev) : CondimentDecorator(bev) {}
    
        std::string getDescription() const override {
            return beverage->getDescription() + ", Milk";
        }
    
        double cost() const override {
            return beverage->cost() + 0.5; // ミルクは追加料金がかかる
        }
    };
    #include "CondimentDecorator.h"
    
    // 具象デコレーター - シロップ
    class Syrup : public CondimentDecorator {
    public:
        Syrup(Beverage* bev) : CondimentDecorator(bev) {}
    
        std::string getDescription() const override {
            return beverage->getDescription() + ", Syrup";
        }
    
        double cost() const override {
            return beverage->cost() + 0.25; // シロップは追加料金がかかる
        }
    };

    Main関数(main.cpp)

    #include "Espresso.h"
    #include "Milk.h"
    #include "Syrup.h"
    
    int main() {
        Beverage* beverage = new Espresso(); // ベースのコーヒーを注文
    
        // コーヒーのみの値段を確認
        std::cout << "Order: " << beverage->getDescription() << std::endl;
        std::cout << "Total cost: $" << beverage->cost() << std::endl;
        std::cout << "" << std::endl;
    
        // ミルクを追加
        beverage = new Milk(beverage);
    
        // シロップを追加
        beverage = new Syrup(beverage);
    
        std::cout << "Order: " << beverage->getDescription() << std::endl;
        std::cout << "Total cost: $" << beverage->cost() << std::endl;
    
        delete beverage; // メモリリークを防ぐために解放
    
        return 0;
    }

    サンプルコードの実行結果

    実行結果は以下のようになります。

    デコレーターを追加した結果が反映されています。

    Order: Espresso
    Total cost: $1.99
    
    Order: Espresso, Milk, Syrup
    Total cost: $2.74
    この記事を書いている人 - WRITER -
    ゲーム音楽をこよなく愛するものです。 このブログではゲーム音楽に関する記事や大学生活に関する記事、ブログに関する記事を紹介します。 超絶田舎の地方国立大学に通ってます。週1くらいで更新してるので暇なときに見に来てください。たまに面白い記事書いてます。彼女募集中!!←≪重要≫  
    詳しいプロフィールはこちら

    - Comments -

    メールアドレスが公開されることはありません。 が付いている欄は必須項目です

    このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

    Copyright© WATA-BLOG(わたブログ) , 2024 All Rights Reserved.