C++で読むデザインパターン(Design Patterns read by C++)
C++で読むデザインパターン(Design Patterns read by C++)



 デザインパターンの本って、眠い本が多いですね。^^; 「そんな薀蓄はいいから、コードで書いて見せてよ」という人(私)のために C++ のコードでデザインパターンを紹介します。とはいえ、やまざきの頭で解釈したことをそのままコードに書き出していますので、パターンの解釈の仕方が間違っているかもしれません。よって、これらのコードを鵜呑みにせず、各自 GoF 本などと照らし合わせて利用することをお薦めします。

 パターンは主にオブジェクト指向の「継承機能」を使って実装されますが、C++ のテンプレートやリファレンスを使うことで継承を使わなくても ある程度実装できるパターンがあります。その継承を使わないパターンを「非継承版」として掲載しています(個人的には継承という概念が嫌いなので^^;)。継承版と非継承版は同じ動作をします(実装方法が違う)のでコードを比べてみると良いと思います。まぁ、「非継承版」の方は お遊びのコードというか「こう書いてもいいじゃん」という、お試しのサンプルコードなのであまり本気にしないで下さい。
#非継承版って、実はジェネリックなコード(型に依存しないコード)であることに最近気が付きました。結構すごいことかも。

 全23パターンを C++ で書いてみて思ったことは「デザインパターン」とは「設計の定石」のことなんだと思いました。「ここはこんなパターンで構築できるね」とか、「ここのコードはxxxのパターンで書かれているね」という会話が出来るようになればデザインパターンの恩恵を受けてコードの生産性を上げられるのでしょう。
 なにかおかしなコードを発見した場合は連絡を下さい。これらのコードがみなさんのお役にたてば嬉しく思います。

あ、あと、このページをそのまま本にしませんか? この原稿を本にしてくれる出版社さんも募集しています。
こういう、シンプルなコードって、とっても重要だと思うのです。いやホントに。連絡をお待ちしています。
英語とか韓国語、中国語での出版も希望しています。
よろしくお願いします。
分類 パターン名 概要
構造 Adapter Adapter (非継承版) インターフェース(構造)の共通化
Bridge Bridge (非継承版) インターフェースを分離
Composite Composite (非継承版) 入れ物と入れるモノを同じインターフェース(構造)に
Decorator Decorator (非継承版) 同じインターフェース(構造)で拡張
Facade Facade (非継承版) 簡単なインターフェース(構造)を提供
Flyweight Flyweight (非継承版) インスタンスを共有
Proxy Proxy (非継承版) 代理(仲介者)を通す構造
振る舞い Chain of Responsibility Chain of Responsibility
(非継承版)
たらい回しする振る舞い
Command Command (非継承版) 実行部分を共通インターフェースに
Interpreter ミニ言語の構築
Iterator ←同梱 ポインタのような振る舞い
Mediator Mediator (非継承版) まとめ者のいる振る舞い
同→ Memento(非継承版) 情報をセーブする振る舞い
Observer Observer (非継承版) 観察者に知らされる振る舞い
State State(非継承版) 状態をインスタンスにする
Strategy Strategy (非継承版) アルゴリズムを入れ替える
TemplateMethod TemplateMethod
(非継承版)
一部の機能を後で実装する
Visitor Visitor (非継承版) 訪れて処理する振る舞い
生成 AbstractFactory AbstractFactory (非継承版) 抽象的な製品を生成する抽象的な工場
Builder Builder (非継承版) 生成過程を共通化
FactoryMethod FactoryMethod (非継承版) インスタンスの生成は後で実装
Prototype Prototype (非継承版) クローンを生成する
Singleton Singleton (非継承版) インスタンスを一つしか生成しない

[構造] Adapter パターン
共通インターフェイスを提供する。
#include <stdio.h> // puts()

// 既存のクラス(インターフェースがバラバラ)

class Apple
{
public:
    void AppleName()
    {
        puts( "りんご" ) ;
    }
    void AppleColor()
    {
        puts( "赤" ) ;
    }
} ;

class Banana
{
public:
    void BananaName()
    {
        puts( "バナナ" ) ;
    }
    void BananaColor()
    {
        puts( "黄" ) ;
    }
} ;

// Adapter パターン

// 共通インターフェースを作る
class AdapterPtn
{
public:
    virtual void  NamePuts()  = 0 ;
    virtual void  ColorPuts() = 0 ;
} ;

// 共通インターフェースにあわせる
class Apple2 : public AdapterPtn
{
    Apple  m_apple ;

public:
    virtual void NamePuts()
    {
        m_apple.AppleName() ;
    }
    virtual void ColorPuts()
    {
        m_apple.AppleColor() ;
    }
} ;

class Banana2 : public AdapterPtn
{
    Banana  m_banana ;

public:
    virtual void NamePuts()
    {
        m_banana.BananaName() ;
    }
    virtual void ColorPuts()
    {
        m_banana.BananaColor() ;
    }
} ;

// 実装
// ポインタで受け取るのは好きじゃないんだけど
void sub( AdapterPtn * in )
{
    // 共通インターフェースで呼べる
    in->NamePuts() ;
    in->ColorPuts() ;
}

int main()
{
    Apple2   a2 ; sub( & a2 ) ;
    Banana2  b2 ; sub( & b2 ) ;

    return 0 ;
}

/* 実行結果
りんご

バナナ

Press any key to continue
*/

[構造] Adapter パターン (非継承版)
共通インターフェイスを提供する。
#include <stdio.h> // puts()

// 既存のクラス(インターフェースがバラバラ)

class Apple
{
public:
    void AppleName()
    {
        puts( "りんご" ) ;
    }
    void AppleColor()
    {
        puts( "赤" ) ;
    }
} ;

class Banana
{
public:
    void BananaName()
    {
        puts( "バナナ" ) ;
    }
    void BananaColor()
    {
        puts( "黄" ) ;
    }
} ;

// Adapter パターン

// template の場合は、共通インターフェースを作る必要は無い。

// 共通インターフェースにあわせる
class Apple2
{
    Apple  m_apple ;

public:
    void NamePuts() // 共通インターフェース
    {
        m_apple.AppleName() ;
    }
    void ColorPuts() // 共通インターフェース
    {
        m_apple.AppleColor() ;
    }
} ;

class Banana2
{
    Banana  m_banana ;

public:
    void NamePuts() // 共通インターフェース
    {
        m_banana.BananaName() ;
    }
    void ColorPuts() // 共通インターフェース
    {
        m_banana.BananaColor() ;
    }
} ;

// 実装

templateclass _AdapterPtn >
void sub( _AdapterPtn & in )
{
    // 共通インターフェースで呼べる
    in.NamePuts() ;
    in.ColorPuts() ;
}

int main()
{
    Apple2   a2 ; sub( a2 ) ;
    Banana2  b2 ; sub( b2 ) ;

    return 0 ;
}

/* 実行結果
りんご

バナナ

Press any key to continue
*/

[構造] Bridge パターン
インターフェイスを2つに分けて橋渡し。それぞれ個別に拡張可能にする。
#include <stdio.h>  // printf()

// インターフェース(下部)
class BridgeLowPtn
{
public:
    virtual void  NamePuts() = 0 ; // 共通 Low インターフェース
} ;

// インターフェース(上部)
class BridgeHiPtn
{
public:
    BridgeLowPtn *  m_low ; // Low とつながっている

    BridgeHiPtn( BridgeLowPtn *  in ) // Low と結合
    : m_low( in )
    {}

    virtual void  Puts() = 0 ; // 共通 Hi インターフェース
} ;

// 実装

class Apple : public BridgeLowPtn
{
public:
    virtual void  NamePuts() // 共通 Low インターフェース
    {
        printf( "リンゴ" ) ;
    }
};

class Banana : public BridgeLowPtn
{
public:
    virtual void  NamePuts() // 共通 Low インターフェース
    {
        printf( "バナナ" ) ;
    }
};

class Hirosue : public BridgeHiPtn
{
public:
    Hirosue( BridgeLowPtn * in )
    : BridgeHiPtn( in )
    {}
    
    // Hi と Low のインターフェースを橋渡しする
    virtual void  Puts()     // 共通 Hi インターフェース
    {
        m_low->NamePuts() ;  // 共通 Low インターフェース
        printf( "をください\n" ) ;
    }
};

class Honjyo : public BridgeHiPtn
{
public:
    Honjyo( BridgeLowPtn * in )
    : BridgeHiPtn( in )
    {}
    
    // Hi と Low のインターフェースを橋渡しする
    virtual void  Puts()     // 共通 Hi インターフェース
    {
        m_low->NamePuts() ;  // 共通 Low インターフェース
        printf( "がほしいねん\n" ) ;
    }
};

void sub( BridgeLowPtn * in_fruit )
{
    Hirosue  ryoko( in_fruit ) ;
    ryoko.Puts() ;

    Honjyo  manami( in_fruit ) ;
    manami.Puts() ;
}

int main()
{
    Apple   apple ;  sub( & apple ) ;
    Banana  banana ; sub( & banana ) ;

    return 0 ;
}

/* 実行結果
リンゴをください
リンゴがほしいねん
バナナをください
バナナがほしいねん
Press any key to continue
*/

[構造] Bridge パターン (非継承版)
インターフェイスを2つに分けて橋渡し。それぞれ個別に拡張可能にする。
#include <stdio.h>  // printf()

// 実装

class Apple
{
public:
    void  NamePuts() // 共通 Low インターフェース
    {
        printf( "リンゴ" ) ;
    }
};

class Banana
{
public:
    void  NamePuts() // 共通 Low インターフェース
    {
        printf( "バナナ" ) ;
    }
};

templateclass _BridgeLowPtn >
class Hirosue
{
    _BridgeLowPtn &  m_low ;

public:
    Hirosue( _BridgeLowPtn & in )
    : m_low( in )
    {}
    
    // Hi と Low のインターフェースを橋渡しする
    void  Puts()            // 共通 Hi インターフェース
    {
        m_low.NamePuts() ;  // 共通 Low インターフェース
        printf( "をください\n" ) ;
    }
} ;

templateclass _BridgeLowPtn >
class Honjyo
{
    _BridgeLowPtn &  m_low ;

public:
    Honjyo( _BridgeLowPtn & in )
    : m_low( in )
    {}

    // Hi と Low のインターフェースを橋渡しする
    void  Puts()            // 共通 Hi インターフェース
    {
        m_low.NamePuts() ;  // 共通 Low インターフェース
        printf( "がほしいねん\n" ) ;
    }
};

templateclass _BridgeLowPtn >
void sub( _BridgeLowPtn & in_fruit )
{
    Hirosue< _BridgeLowPtn >  ryoko( in_fruit ) ;
    ryoko.Puts() ;  // 共通 Hi インターフェース

    Honjyo< _BridgeLowPtn >  manami( in_fruit ) ;
    manami.Puts() ;  // 共通 Hi インターフェース
}

int main()
{
    Apple   apple ;  sub( apple ) ;
    Banana  banana ; sub( banana ) ;

    return 0 ;
}

/* 実行結果
リンゴをください
リンゴがほしいねん
バナナをください
バナナがほしいねん
Press any key to continue
*/

[構造] Composite パターン
入れ物(器)と入れるモノを同じインターフェースにする。
木構造などの再起構造を使いたいときに使うパターン。
「枝」と「葉」に分けた場合、枝には枝と葉の両方を追加できる。
#include <stdio.h> // puts()
#include <string>  // STL  std::string

// Compositeパターン

class CompositePtn
{
public:
    std::string  m_name ;  // 名前

    CompositePtn( const std::string &  in_name )
    : m_name( in_name )
    {}

    // 共通インターフェース
    virtual void  Puts( const std::string &  in_parent ) = 0 ;
} ;

// 実装

// 葉
class Leaf : public CompositePtn
{
public:
    Leaf( const std::string &  in_name )
    : CompositePtn( in_name )
    {}

    // 共通インターフェース
    virtual void  Puts( const std::string &  in_parent )
    {
        std::string  str = in_parent + "/" + m_name ;

        puts( str.c_str() ) ;
    }
} ;

// 葉(終端)
class Null : public CompositePtn
{
public:
    Null()
    : CompositePtn( "" )
    {}

    // 共通インターフェース
    virtual void  Puts( const std::string &  in_parent )
    {}
} ;

// 枝
class Tree : public CompositePtn
{
    // std::vector<CompositePtn *> tbl ; でも可
    CompositePtn *  m_left ;  // 左の枝
    CompositePtn *  m_right ; // 右の枝

public:
    Tree(
        const std::string &  in_name,
        CompositePtn *       in_left,
        CompositePtn *       in_right
    )
    : CompositePtn( in_name )
    , m_left(  in_left  )
    , m_right( in_right )
    {}
    
    // 共通インターフェース
    virtual void  Puts( const std::string &  in_parent )
    {
        std::string  str = in_parent + "/" + m_name ;

        puts( str.c_str() ) ;

        // 枝をたどる
        m_left->Puts( str ) ;
        m_right->Puts( str ) ;
    }
};


int main()
{
    // honjyo には apple と banana
    Leaf  apple( "apple" ) ;
    Leaf  banana( "banana" ) ;
    Tree  honjyo( "honjyo", &apple, &banana ) ;

    // hirosue には cacao だけ
    Leaf  cacao( "cacao" ) ;
    Null  null ;
    Tree  hirosue( "hirosue", &cacao, &null ) ;

    // 木の根っこ
    // 左の枝には honjyo 右の枝には hirosue
    Tree  root( "root", &honjyo, &hirosue ) ;

    // 全部表示してみましょう。
    root.Puts( "" ) ;

    return  0 ;
}

/* 実行結果
/root
/root/honjyo
/root/honjyo/apple
/root/honjyo/banana
/root/hirosue
/root/hirosue/cacao
Press any key to continue
*/



[構造] Composite パターン(非継承版)
入れ物(器)と入れるモノを同じインターフェースにする。
木構造などの再起構造を使いたいときに使うパターン。
「枝」と「葉」に分けた場合、枝には枝と葉の両方を追加できる。
#include <stdio.h> // puts()
#include <string>  // STL  std::string

// Compositeパターン

// 実装

// 葉
class Leaf
{
    const std::string  m_name ;

public:
    Leaf( const std::string  in_name )
    : m_name( in_name )
    {}

    // 共通インターフェース
    void  Puts( const std::string &  in_parent )
    {
        std::string  str = in_parent + "/" + m_name ;

        puts( str.c_str() ) ;
    }
} ;

// 葉(終端)
class Null
{
public:
    Null(){}

    // 共通インターフェース
    void  Puts( const std::string &  in_parent )
    {}
} ;

// 枝
templateclass _Left, class _Right >
class Tree
{
    const std::string  m_name ;

    _Left &   m_left ;  // 左の枝
    _Right &  m_right ; // 右の枝

public:
    Tree(
        const std::string  in_name,
        _Left &            in_left,
        _Right &           in_right
    )
    : m_name(  in_name )
    , m_left(  in_left )
    , m_right( in_right )
    {}
    
    // 共通インターフェース
    void  Puts( const std::string &  in_parent )
    {
        std::string  str = in_parent + "/" + m_name ;

        puts( str.c_str() ) ;

        // 枝をたどる
        m_left.Puts( str ) ;
        m_right.Puts( str ) ;
    }
};


int main()
{
    // honjyo には apple と banana
    Leaf                apple( "apple" ) ;
    Leaf                banana( "banana" ) ;
    Tree< Leaf, Leaf >  honjyo( "honjyo", apple, banana ) ;

    // hirosue には cacao だけ
    Leaf                cacao( "cacao" ) ;
    Null                null ;
    Tree< Leaf, Null >  hirosue( "hirosue", cacao, null ) ;

    // 木の根っこ
    // 左の枝には honjyo 右の枝には hirosue
    // なんか、すでに保守できないくらい複雑になっている^^;
    Tree< Tree< Leaf, Leaf >, Tree< Leaf, Null > >
        root( "root", honjyo, hirosue ) ;

    // 全部表示してみましょう。
    root.Puts( "" ) ;

    return  0 ;
}

/* 実行結果
/root
/root/honjyo
/root/honjyo/apple
/root/honjyo/banana
/root/hirosue
/root/hirosue/cacao
Press any key to continue
*/

[構造] Decorator パターン
同じインターフェースで拡張するイメージ。機能を付加(飾り付け)するパターン。
#include <stdio.h> // puts()

// Decoratorパターン

class DecoratorPtn
{
public:
    virtual void  Puts() = 0 ; // インターフェース
} ;

// 実装

class Apple : public DecoratorPtn
{
public:
    virtual void  Puts() // インターフェース
    {
        puts( "リンゴ" ) ;
    }
} ;

class Banana : public DecoratorPtn
{
public:
    virtual void  Puts() // インターフェース
    {
        puts( "バナナ" ) ;
    }
};

class Good : public DecoratorPtn
{
    DecoratorPtn *  m_p_decorator ;

public:
    Good( DecoratorPtn* in )
    : m_p_decorator( in )
    {}
    
    virtual void Puts()   // 拡張インターフェース
    {
        printf( "おいしい" ) ;
        m_p_decorator->Puts() ; // オリジナルを呼ぶ
    }
} ;

void sub( DecoratorPtn* in )
{
    in->Puts() ;

    // 拡張その1
    Good  good( in ) ;
    good.Puts() ;

    // 拡張その2
    Good  verygood( & good ) ;
    verygood.Puts() ;
}

int main()
{
    Apple   apple ;  sub( & apple ) ;
    Banana  banana ; sub( & banana ) ;

    return  0 ;
}

/* 実行結果
リンゴ
おいしいリンゴ
おいしいおいしいリンゴ
バナナ
おいしいバナナ
おいしいおいしいバナナ
Press any key to continue
*/

[構造] Decorator パターン (非継承版)
同じインターフェースで拡張するイメージ。機能を付加(飾り付け)するパターン。
#include <stdio.h> // puts()

// Decoratorパターン

// 実装

class Apple
{
public:
    void  Puts()  // インターフェース
    {
        puts( "リンゴ" ) ;
    }
} ;

class Banana
{
public:
    void  Puts()  // インターフェース
    {
        puts( "バナナ" ) ;
    }
};

templateclass _DecoratorPtn >
class Good 
{
    _DecoratorPtn &  m_decorator ;

public:
    Good( _DecoratorPtn & in  )
    : m_decorator( in )
    {}

    void Puts()   // 拡張インターフェース
    {
        printf( "おいしい" ) ;
        m_decorator.Puts() ; // オリジナルを呼ぶ
    }
} ;

templateclass _ObjectPtn >
void sub( _ObjectPtn in )
{
    in.Puts() ;

    // 拡張その1
    Good< _ObjectPtn >  good( in ) ;
    good.Puts() ;

    // 拡張その2
    Good< Good< _ObjectPtn > >  verygood( good ) ;
    verygood.Puts() ;
}

int main()
{
    Apple   apple ;  sub( apple ) ;
    Banana  banana ; sub( banana ) ;

    return  0 ;
}

/* 実行結果
リンゴ
おいしいリンゴ
おいしいおいしいリンゴ
バナナ
おいしいバナナ
おいしいおいしいバナナ
Press any key to continue
*/

[構造] Facade パターン
複雑な処理を簡単なインターフェースで提供する。
#include <stdio.h> // printf()

// もともとある実装(本当はもっと複雑なクラスだと思われ^^;)

class Apple
{
public:
    int value_Get()
    {
        return 120 ;
    }
} ;

class Banana
{
public:
    int value_Get()
    {
        return 60 ;
    }
} ;

// Facadeパターンだけど、パターンと言えるのかね。

class FacadePtn
{
public:
    virtual void  Shopping() = 0 ; // 簡単なメソッド
} ;

// 実装

class Hirosue : public FacadePtn
{
public:
    virtual void  Shopping()
    {
        // 複雑な処理?を隠す
        Apple   apple ;
        Banana  banana ;
        int     val = 0 ;

        val += apple.value_Get()  * 2 ; // リンゴ2個
        val += banana.value_Get() * 3 ; // バナナ3個

        printf( "%d円じゃん。\n", val ) ;
    }
} ;

class Honjyo : public FacadePtn
{
public:
    virtual void  Shopping()
    {
        // 複雑な処理?を隠す
        Banana  banana ;
        int     val = banana.value_Get() * 50 ; // バナナ50個

        printf( "%d円やねん。\n", val ) ;
    }
} ;

void sub( FacadePtn * in )
{
    in->Shopping() ;
}

int main()
{
    Hirosue  ryoko ; sub( & ryoko ) ;
    Honjyo  manami ; sub( & manami ) ;

    return 0 ;
}

/* 実行結果
420円じゃん。
3000円やねん。
Press any key to continue
*/

[構造] Facade パターン (非継承版)
複雑な処理を簡単なインターフェースで提供する。
// Facade パターン (template版)

// 複雑な処理を簡単にする。 

#include <stdio.h> // printf()

// もともとある実装(本当はもっと複雑なクラスだと思われ^^;)

class Apple
{
public:
    int value_Get()
    {
        return 120 ;
    }
} ;

class Banana
{
public:
    int value_Get()
    {
        return 60 ;
    }
} ;

// Facadeパターンだけど、パターンと言えるのかね。

// 実装

class Hirosue
{
public:
    void  Shopping()
    {
        // 複雑な処理?を隠す
        Apple   apple ;
        Banana  banana ;
        int     val = 0 ;

        val += apple.value_Get()  * 2 ; // リンゴ2個
        val += banana.value_Get() * 3 ; // バナナ3個

        printf( "%d円じゃん。\n", val ) ;
    }
} ;

class Honjyo
{
public:
    void  Shopping()
    {
        // 複雑な処理?を隠す
        Banana  banana ;
        int     val = banana.value_Get() * 50 ; // バナナ50個

        printf( "%d円やねん。\n", val ) ;
    }
} ;

templateclass _FacadePtn >
void sub( _FacadePtn & in )
{
    in.Shopping() ;
}

int main()
{
    Hirosue  ryoko ; sub( ryoko ) ;
    Honjyo  manami ; sub( manami ) ;

    return 0 ;
}

/* 実行結果
420円じゃん。
3000円やねん。
Press any key to continue
*/

[構造] Flyweight パターン
インスタンスを共有してメモリを軽くする。キャッシュのような考え方だと思う。
Proxy の配列版とも言えるかも。
#include <stdio.h> // printf()

// Flyweight パターン

class FlyweightPtn
{
public:
    virtual void Puts() = 0 ;
} ;

// 実装

class Apple : public FlyweightPtn
{
    char * m_str ;

public:
    Apple()
    {
        // もっとメモリを沢山必要とするclassだと思われ
        m_str = "+--------+\n| リンゴ |\n+--------+" ;
    }

    virtual void Puts()
    {
        puts( m_str ) ;
    }
} ;

class Banana : public FlyweightPtn
{
    char * m_str ;

public:
    Banana()
    {
        // もっとメモリを沢山必要とするclassだと思われ
        m_str = "onnnnnnnno\n8 バナナ 8\n8uuuuuuuu8" ;
    }

    virtual void Puts()
    {
        puts( m_str ) ;
    }
} ;

class FlyweightFactory
{
    // インスタンス化するのは2つ
    Apple           m_apple ;
    Banana          m_banana ;
    FlyweightPtn *  m_p_tbl[4] ;

public:
    FlyweightFactory()
    {
        // 4つ分のインスタンス(メモリ)を2つ分に減らす。
        m_p_tbl[0] = & m_apple ;
        m_p_tbl[1] = & m_apple ;
        m_p_tbl[2] = & m_banana ;
        m_p_tbl[3] = & m_banana ;
    }

    void Put( int in )
    {
        m_p_tbl[ in % 4 ]->Puts() ;
    }
} ;


int main()
{
    FlyweightFactory  factory ;

    for ( int i=0 ; i<6 ; ++i )
    {
        factory.Put( i ) ;
    }

    return  0 ;
}

/* 実行結果
+--------+
| リンゴ |
+--------+
+--------+
| リンゴ |
+--------+
onnnnnnnno
8 バナナ 8
8uuuuuuuu8
onnnnnnnno
8 バナナ 8
8uuuuuuuu8
+--------+
| リンゴ |
+--------+
+--------+
| リンゴ |
+--------+
Press any key to continue
*/


[構造] Flyweight パターン(非継承版)
template ではできないね。
インスタンスを共有してメモリを軽くする。キャッシュのような考え方だと思う。
Proxy の配列版とも言えるかも。
#include <stdio.h> // printf()

// Flyweight パターン(非継承版)

// 実装
class Apple
{
    char * m_str ;

public:
    Apple()
    {
        // もっとメモリを沢山必要とするclassだと思われ
        m_str = "+--------+\n| リンゴ |\n+--------+" ;
    }

    virtual void Puts()
    {
        puts( m_str ) ;
    }
} ;

class Banana
{
    char * m_str ;

public:
    Banana()
    {
        // もっとメモリを沢山必要とするclassだと思われ
        m_str = "onnnnnnnno\n8 バナナ 8\n8uuuuuuuu8" ;
    }

    virtual void Puts()
    {
        puts( m_str ) ;
    }
} ;

class FlyweightFactory
{
    // インスタンス化するのは2つ
    Apple   m_apple ;
    Banana  m_banana ;

public:
    void Put( int in )
    {
        // 4つ分のインスタンス(メモリ)を2つ分に減らす。
        // わざわざパターンにしなくても switch で良いと思うのだけど
        // 数が多くなるとたいへんだけどね。^^;
        switch( in % 4 )
        {
            case 0 : m_apple.Puts() ; break ;
            case 1 : m_apple.Puts() ; break ;
            case 2 : m_banana.Puts() ; break ;
            case 3 : m_banana.Puts() ; break ;
        }
    }
} ;


int main()
{
    FlyweightFactory  factory ;

    for ( int i=0 ; i<6 ; ++i )
    {
        factory.Put( i ) ;
    }

    return  0 ;
}
/* 実行結果
+--------+
| リンゴ |
+--------+
+--------+
| リンゴ |
+--------+
onnnnnnnno
8 バナナ 8
8uuuuuuuu8
onnnnnnnno
8 バナナ 8
8uuuuuuuu8
+--------+
| リンゴ |
+--------+
+--------+
| リンゴ |
+--------+
Press any key to continue
*/



[構造] Proxy パターン
代理(仲介者)を通すパターン。これは分かりやすいし簡単だよね。
キャッシュのパターンにも使える。
Decorator にも似ているが、Proxy は機能拡張をしない。
#include <stdio.h>

// Proxyパターン
// オリジナルも代理も同じインターフェースを使う

class ProxyPtn
{
public:
    virtual void  Eat() = 0 ;
} ;

// 実装 オリジナル

class Apple : public ProxyPtn
{
public:
    Apple()
    {
        puts( "リンゴを買う。" ) ;
    }

    virtual void  Eat()
    {
        puts( "あー、おいしい。" ) ;
    }
} ;

// 実装 代理

class AppleProxy : public ProxyPtn
{
    Apple *  m_p_apple ;

public:
    AppleProxy()
    : m_p_apple( 0 ) // 必要になるまで作らないことにする
    {}

    ~AppleProxy()
    {
        if ( m_p_apple != 0 )
        {
            delete m_p_apple ;
            m_p_apple = 0 ;
        }
    }

    virtual void  Eat()
    {
        if ( m_p_apple == 0 )
        {
            // 無いので作る
            m_p_apple = new Apple ;
        }
        m_p_apple->Eat() ;
    }
} ;

int main()
{
    puts( "----オリジナル-----" ) ;
    {
        Apple  apple1 ;
        Apple  apple2 ;
        Apple  apple3 ;

        // 3つ買ったけど、食べるのは1つ
        apple1.Eat() ;
        apple1.Eat() ;
    }

    puts( "----代理-----" ) ;
    {
        AppleProxy  proxy1 ;
        AppleProxy  proxy2 ;
        AppleProxy  proxy3 ;

        // 3つ買ったけど、食べるのは1つ
        proxy1.Eat() ;
        proxy1.Eat() ;
    }

    return  0 ;
}

/* 実行結果
----オリジナル-----
リンゴを買う。
リンゴを買う。
リンゴを買う。
あー、おいしい。
あー、おいしい。
----代理-----
リンゴを買う。
あー、おいしい。
あー、おいしい。
Press any key to continue
*/

[構造] Proxy パターン (非継承版)
代理(仲介者)を通すパターン。これは分かりやすいし簡単だよね。
キャッシュのパターンにも使える。
Decorator にも似ているが、Proxy は機能拡張をしない。
#include <stdio.h>
#include <vector>  // std::vector
 
// Proxyパターン

// 実装 オリジナル

class Apple
{
public:
    Apple()
    {
        puts( "リンゴを買う。" ) ;
    }

    void  Eat()
    {
        puts( "あー、おいしい。" ) ;
    }
} ;

// 実装 代理

class AppleProxy
{
    // std::vector を使って強引に構築してみました。
    // 効率的とは言い難いが、ま、ご参考ってことで。^^;
    std::vector< Apple >  m_apple ;

public:
    virtual void  Eat()
    {
        if ( m_apple.size() == 0 )
        {
            // コピーコンストラクタも動いちゃうけどね
            m_apple.resize( 1 ) ;
        }
        m_apple[0].Eat() ;
    }
} ;

int main()
{
    puts( "----オリジナル-----" ) ;
    {
        Apple  apple1 ;
        Apple  apple2 ;
        Apple  apple3 ;

        // 3つ買ったけど、食べるのは1つ
        apple1.Eat() ;
        apple1.Eat() ;
    }

    puts( "----代理-----" ) ;
    {
        AppleProxy  proxy1 ;
        AppleProxy  proxy2 ;
        AppleProxy  proxy3 ;

        // 3つ買ったけど、食べるのは1つ
        proxy1.Eat() ;
        proxy1.Eat() ;
    }

    return  0 ;
}

/* 実行結果
----オリジナル-----
リンゴを買う。
リンゴを買う。
リンゴを買う。
あー、おいしい。
あー、おいしい。
----代理-----
リンゴを買う。
あー、おいしい。
あー、おいしい。
Press any key to continue
*/

[振る舞い] Chain of Responsibility パターン
バケツリレー(「たらい回し」ともいう)なパターン
#include <stdio.h> // printf()

// Chain of Responsibility パターン

class ChainPtn
{
public:
    virtual void  Shopping( int in ) = 0 ;
} ;

// 実装

class Apple : public ChainPtn
{
    ChainPtn *  m_chain ; // 次

public:
    Apple( ChainPtn* in )
    : m_chain( in )
    {}
    
    virtual void  Shopping( int in )
    {
        printf( "所持金%4d 円。", in ) ;
        if ( in >= 120 )
        {
            printf( "リンゴ(120円)を1つ買う ->\n" ) ;
            in -= 120 ;
        }
        else
        {
            printf( "リンゴ(120円)は買えない ->\n" ) ;
        }
        m_chain->Shopping( in ) ; // 次の店(ここがミソ)
    }
} ;

class Banana : public ChainPtn
{
    ChainPtn *  m_chain ; // 次

public:
    Banana( ChainPtn* in )
    : m_chain( in )
    {}
    
    virtual void Shopping( int in )
    {
        printf( "所持金%4d 円。", in ) ;
        if ( in >= 60 )
        {
            printf( "バナナ(60円)を1つ買う ->\n" ) ;
            in -= 60 ;
        }
        else
        {
            printf( "バナナ(60円)は買えない ->\n" ) ;
        }
        m_chain->Shopping( in ) ; // 次の店(ここがミソ)
    }    
} ;

class Home : public ChainPtn
{
public:
    virtual void  Shopping( int in )
    {
        printf( "所持金%4d 円。", in ) ;
        printf( "買い物終わり。おつかれさま。\n" ) ;        
    }
} ;


int main()
{
    Home    home ;              // 買い物終わり。家に帰る。
    Banana  banana( & home ) ;  // バナナを買ったら家に帰る。
    Apple   apple( & banana ) ; // リンゴを買ったらバナナを買う。

    puts( "--- 10円で買い物 ---" ) ;
    apple.Shopping( 10 ) ;

    puts( "--- 100円で買い物 ---" ) ;
    apple.Shopping( 100 ) ;

    puts( "--- 150円で買い物 ---" ) ;
    apple.Shopping( 150 ) ;

    puts( "--- 300円で買い物 ---" ) ;
    apple.Shopping( 300 ) ;

    return  0 ;
}

/* 実行結果
--- 10円で買い物 ---
所持金  10 円。リンゴ(120円)は買えない ->
所持金  10 円。バナナ(60円)は買えない ->
所持金  10 円。買い物終わり。おつかれさま。
--- 100円で買い物 ---
所持金 100 円。リンゴ(120円)は買えない ->
所持金 100 円。バナナ(60円)を1つ買う ->
所持金  40 円。買い物終わり。おつかれさま。
--- 150円で買い物 ---
所持金 150 円。リンゴ(120円)を1つ買う ->
所持金  30 円。バナナ(60円)は買えない ->
所持金  30 円。買い物終わり。おつかれさま。
--- 300円で買い物 ---
所持金 300 円。リンゴ(120円)を1つ買う ->
所持金 180 円。バナナ(60円)を1つ買う ->
所持金 120 円。買い物終わり。おつかれさま。
Press any key to continue
*/

[振る舞い] Chain of Responsibility パターン (非継承版)
バケツリレー(「たらい回し」ともいう)なパターン
#include <stdio.h> // printf()

// 実装

templateclass _ChainPtn >
class Apple
{
    _ChainPtn &  m_chain ; // 次

public:
    Apple( _ChainPtn &  in )
    : m_chain( in )
    {}
    
    void  Shopping( int in )
    {
        printf( "所持金%4d 円。", in ) ;
        if ( in >= 120 )
        {
            printf( "リンゴ(120円)を1つ買う ->\n" ) ;
            in -= 120 ;
        }
        else
        {
            printf( "リンゴ(120円)は買えない ->\n" ) ;
        }
        m_chain.Shopping( in ) ; // 次の店(ここがミソ)
    }
} ;

templateclass _ChainPtn >
class Banana
{
    _ChainPtn &  m_chain ; // 次

public:
    Banana( _ChainPtn &  in )
    : m_chain( in )
    {}
    
    void Shopping( int in )
    {
        printf( "所持金%4d 円。", in ) ;
        if ( in >= 60 )
        {
            printf( "バナナ(60円)を1つ買う ->\n" ) ;
            in -= 60 ;
        }
        else
        {
            printf( "バナナ(60円)は買えない ->\n" ) ;
        }
        m_chain.Shopping( in ) ; // 次の店(ここがミソ)
    }    
} ;

class Home
{
public:
    void  Shopping( int in )
    {
        printf( "所持金%4d 円。", in ) ;
        printf( "買い物終わり。おつかれさま。\n" ) ;        
    }
} ;


int main()
{
    Home                     home ;            // 買い物終わり
    Banana< Home >           banana( home ) ;  // バナナを買ったら家に帰る
    Apple< Banana< Home > >  apple( banana ) ; // リンゴを買ったらバナナを買う

    puts( "--- 10円で買い物 ---" ) ;
    apple.Shopping( 10 ) ;

    puts( "--- 100円で買い物 ---" ) ;
    apple.Shopping( 100 ) ;

    puts( "--- 150円で買い物 ---" ) ;
    apple.Shopping( 150 ) ;

    puts( "--- 300円で買い物 ---" ) ;
    apple.Shopping( 300 ) ;

    return  0 ;
}

/* 実行結果
--- 10円で買い物 ---
所持金  10 円。リンゴ(120円)は買えない ->
所持金  10 円。バナナ(60円)は買えない ->
所持金  10 円。買い物終わり。おつかれさま。
--- 100円で買い物 ---
所持金 100 円。リンゴ(120円)は買えない ->
所持金 100 円。バナナ(60円)を1つ買う ->
所持金  40 円。買い物終わり。おつかれさま。
--- 150円で買い物 ---
所持金 150 円。リンゴ(120円)を1つ買う ->
所持金  30 円。バナナ(60円)は買えない ->
所持金  30 円。買い物終わり。おつかれさま。
--- 300円で買い物 ---
所持金 300 円。リンゴ(120円)を1つ買う ->
所持金 180 円。バナナ(60円)を1つ買う ->
所持金 120 円。買い物終わり。おつかれさま。
Press any key to continue
*/

[振る舞い] Command パターン
実行(execute)部分を共通インターフェースにすることで、
実行結果の保存や再実行などの実装が楽になるパターン。
#include <stdio.h> // puts()

// 既存のclass

class Apple
{
public:
    void  NamePut()
    {
        puts( "これは「リンゴ」です。" ) ;
    }

public:
    void  ColorPut()
    {
        puts( "色は「赤」です。" ) ;
    }
} ;


// Commandパターン、共通インターフェースを提供

class CommandPtn
{
public:
    virtual void  Execute() = 0 ; // 実行
} ;

// 実装

class NameCommand : public CommandPtn
{
    Apple *  m_p_apple ;

public:
    NameCommand( Apple* in )
    {
        m_p_apple = in ;
    }

    virtual void  Execute() // 実行内容を実装
    {
        m_p_apple->NamePut() ;
    }
} ;

class ColorCommand : public CommandPtn
{
    Apple *  m_p_apple ;

public:
    ColorCommand( Apple* in )
    {
        m_p_apple = in ;
    }

    virtual void  Execute() // 実行内容を実装
    {
        m_p_apple->ColorPut() ;
    }
} ;

// コマンド

enum COMMAND
{
    NAME_PUT_CMD  = 0,
    COLOR_PUT_CMD = 1,
} ;

void execute(
    enum COMMAND *  in_tbl,
    int             in_tbl_size,
    Apple &         in_apple
)
{
    NameCommand   apple_name_cmd( & in_apple ) ;
    ColorCommand  apple_color_cmd( & in_apple ) ;

    // コマンド群を登録(配列にする意味があるのかな?^^;)
    // インターフェースが共通だから配列に登録できるってことだよね。
    CommandPtn *  cmd_tbl[2] ;

    cmd_tbl[NAME_PUT_CMD]  = & apple_name_cmd ;
    cmd_tbl[COLOR_PUT_CMD] = & apple_color_cmd ;

    // コマンド実行
    for ( int i=0 ; i<in_tbl_size ; ++i )
    {
        cmd_tbl[ in_tbl[i] ]->Execute() ;
    }
}

int main()
{
    Apple  apple ;

    puts( "----普通に実行----" ) ;
    {
        apple.NamePut() ;
        apple.NamePut() ;
        apple.ColorPut() ;
        apple.ColorPut() ;
    }

    puts( "----コマンドテーブルを作って実行----" ) ;
    {
        enum COMMAND  tbl[] =
        {
            NAME_PUT_CMD,
            NAME_PUT_CMD,
            COLOR_PUT_CMD,
            COLOR_PUT_CMD,
        } ;
        execute( tbl, sizeof(tbl)/sizeof(tbl[0]), apple ) ;
    }

    return  0 ;
}

/* 実行結果
----普通に実行----
これは「リンゴ」です。
これは「リンゴ」です。
色は「赤」です。
色は「赤」です。
----コマンドテーブルを作って実行----
これは「リンゴ」です。
これは「リンゴ」です。
色は「赤」です。
色は「赤」です。
Press any key to continue
*/

[振る舞い] Command パターン (非継承版)
実行(execute)部分を共通インターフェースにすることで、
実行結果の保存や再実行などの実装が楽になるパターン。
#include <stdio.h> // puts()

// 既存のclass

class Apple
{
public:
    void  NamePut()
    {
        puts( "これは「リンゴ」です。" ) ;
    }

public:
    void  ColorPut()
    {
        puts( "色は「赤」です" ) ;
    }
} ;

// コマンド実装

enum COMMAND
{
    NAME_PUT_CMD  = 0,
    COLOR_PUT_CMD = 1,
} ;

void execute(
    enum COMMAND *  in_tbl,
    int             in_tbl_size,
    Apple &         in_apple
)
{
    // わざわざ継承なんてしなくたって、switch でいいのに…
    // と思っったので、継承を使わないで、Command パターンを実装。
    // なぜ、継承にこだわるのかは不明。これじゃだめなの?^^;
    // パターンとは言わないってことかも。

    // コマンド実行
    for ( int i=0 ; i<in_tbl_size ; ++i )
    {
        switch ( in_tbl[i] )
        {
            case NAME_PUT_CMD  : in_apple.NamePut() ;  break ;
            case COLOR_PUT_CMD : in_apple.ColorPut() ; break ;
        } ;
    }
}

int main()
{
    Apple  apple ;

    puts( "----普通に実行----" ) ;
    {
        apple.NamePut() ;
        apple.NamePut() ;
        apple.ColorPut() ;
        apple.ColorPut() ;
    }

    puts( "----コマンドテーブルを作って実行----" ) ;
    {
        enum COMMAND  tbl[] =
        {
            NAME_PUT_CMD,
            NAME_PUT_CMD,
            COLOR_PUT_CMD,
            COLOR_PUT_CMD,
        } ;
        execute( tbl, sizeof(tbl)/sizeof(tbl[0]), apple ) ;
    }

    return  0 ;
}

/* 実行結果
----普通に実行----
これは「リンゴ」です。
これは「リンゴ」です。
色は「赤」です
色は「赤」です
----コマンドテーブルを作って実行----
これは「リンゴ」です。
これは「リンゴ」です。
色は「赤」です
色は「赤」です
Press any key to continue
*/

[振る舞い] Interpreter パターン
ミニ言語の構築ができる。
Composite とほぼ同じだがインタプリタの用途で使う特化したパターンらしい。
#include <stdio.h> // printf()
#include <deque>   // STL std::deque<>

class CompositePtn // Composite パターン
                   // (InterpreterPtn とすべきですが…わざとです^^;)
{
public:
    // 共通インターフェース(実行)
    virtual int  Interpret() = 0 ;
} ;

// 実装

class CommandValue : public CompositePtn
{
public:
    char  m_val ; // '0'〜'9'

    virtual int  Interpret() // 実行
    {
        return  m_val - '0' ;
    }
} ;

class CommandMul : public CompositePtn
{
public:
    CompositePtn *  m_left_value ;
    CompositePtn *  m_right_value ;

    char *          m_syntax ;

    CommandMul()
    {
        // E -> E * F
        m_syntax = "E -> E * F" ;
    }

    virtual int  Interpret() // 実行
    {
        int l = m_left_value->Interpret() ;
        int r = m_right_value->Interpret() ;
        int a = l * r ;
        printf( "interpret trace: %d = %d * %d\n", a, l, r ) ;

        return  a ;
    }
} ;

class CommandDiv : public CompositePtn
{
public:
    CompositePtn *  m_left_value ;
    CompositePtn *  m_right_value ;

    char *          m_syntax ;

    CommandDiv()
    {
        // E -> E / F
        m_syntax = "E -> E / F" ;
    }

    virtual int  Interpret() // 実行
    {
        int l = m_left_value->Interpret() ;
        int r = m_right_value->Interpret() ;
        int a = l / r ;
        printf( "interpret trace: %d = %d / %d\n", a, l, r ) ;

        return  a ;
    }
} ;

class CommandAdd : public CompositePtn
{
public:
    CompositePtn *  m_left_value ;
    CompositePtn *  m_right_value ;

    char *          m_syntax ;

    CommandAdd()
    {
        // E -> E + E
        m_syntax = "E -> E + E" ;
    }

    virtual int  Interpret() // 実行
    {
        int l = m_left_value->Interpret() ;
        int r = m_right_value->Interpret() ;
        int a = l + r ;
        printf( "interpret trace: %d = %d + %d\n", a, l, r ) ;

        return  a ;
    }
} ;

class CommandSub : public CompositePtn
{
public:
    CompositePtn *  m_left_value ;
    CompositePtn *  m_right_value ;

    char *          m_syntax ;

    CommandSub()
    {
        // E -> E - E
        m_syntax = "E -> E - E" ;
    }

    virtual int Interpret() // 実行
    {
        int l = m_left_value->Interpret() ;
        int r = m_right_value->Interpret() ;
        int a = l - r ;
        printf( "interpret trace: %d = %d - %d\n", a, l, r ) ;

        return  a ;
    }
} ;

class StackTbl
{
    // 処理中のコマンドと構文
    std::deque< char >            m_command_stack ;
    std::deque< CompositePtn * >  m_syntax_stack ;

    // 確定した構文(delete 用)
    std::deque< CompositePtn * >  m_delete_tbl ;

public:
    ~StackTbl()
    {
        for ( int i=0 ; i<m_delete_tbl.size() ; ++i )
        {
            delete m_delete_tbl[i] ;
        }
    }

    void CommandStackPut()
    {
        printf( "command_stack: " ) ;
        int i = m_command_stack.size()-1 ;
        for ( ; i>=0 ; --i )
        {
            printf( "%c, ", m_command_stack[i] ) ;
        }
        printf( "\n" ) ;
    }

    // 構文解析
    templateclass _Command >
    bool  Parse( _Command & in_cmd )
    {
        //  _1234_6_8_
        // "0 -> 5 7 9" ;
        if ( m_command_stack.size() > 2
          && m_command_stack[2] == in_cmd.m_syntax[5]
          && m_command_stack[1] == in_cmd.m_syntax[7]
          && m_command_stack[0] == in_cmd.m_syntax[9]
           )
        {} else return false ; // NG

        printf( "syntax trace : '%s'\n", in_cmd.m_syntax ) ;

        // m_syntax に登録(CompositePtn の Tree を作成)
        _Command *  cmd = new _Command() ;
        m_delete_tbl.push_back( cmd ) ; // delete 用

        cmd->m_right_value = m_syntax_stack[0] ;
        m_syntax_stack.pop_front() ;
        cmd->m_left_value  = m_syntax_stack[0] ;
        m_syntax_stack.pop_front() ;
        m_syntax_stack.push_front( cmd ) ;

        // m_command を更新
        m_command_stack.pop_front() ;
        m_command_stack.pop_front() ;
        m_command_stack[0] = in_cmd.m_syntax[0] ;

        return true ; // OK
    }

    bool  ParseValue()
    {
        if ( m_command_stack.size() > 0
          && m_command_stack[0] >= '0'  // 数値
          && m_command_stack[0] <= '9'  // 数値
           )
        {} else return false ; // NG

        printf( "syntax trace : value %c\n", m_command_stack[0] ) ;

        // m_syntax に登録(CompositePtn の Leaf を作成)
        CommandValue *  val = new CommandValue() ;
        m_delete_tbl.push_back( val ) ;    // delete 用

        val->m_val = m_command_stack[0] ;
        m_syntax_stack.push_front( val ) ;

        // m_command を更新
        m_command_stack[0] = 'F' ; // 数値 -> _F_

        return true ; // OK
    }

    // E -> F
    bool  ParseEF()
    {
        if ( m_command_stack.size() > 0
          && m_command_stack[0] == 'F'
           )
        {} else return false ; // NG

        m_command_stack[0] = 'E' ;

        return true ; // OK
    }

    void  CommandPush( char  in )
    {
        m_command_stack.push_front( in ) ;
    }

    // 実行(最後に残った CompositePtn の根っこを実行)
    int  Interpret()
    {
        if ( m_command_stack.size() != 1
          || m_command_stack[0]     != 'E'
           )
        {
            puts( "syntax error" ) ;
            return  0 ; // DUMMY
        }

        return  m_syntax_stack[0]->Interpret() ;
    }
} ;

// インタープリタ

int  interpret( char * in_cmd )
{
    StackTbl  stack_tbl ;

    CommandMul  cmd_mul ;
    CommandDiv  cmd_div ;
    CommandAdd  cmd_add ;
    CommandSub  cmd_sub ;

    // 構文解析
    int size = strlen( in_cmd ) ;
    int i = 0 ;
    for ( ; ; ) // Hit しなくなるまで繰り返す
    {
        stack_tbl.CommandStackPut() ;

        if ( stack_tbl.ParseValue()     ) continue ;
        if ( stack_tbl.Parse( cmd_mul ) ) continue ;
        if ( stack_tbl.Parse( cmd_div ) ) continue ;
        if ( stack_tbl.Parse( cmd_add ) ) continue ;
        if ( stack_tbl.Parse( cmd_sub ) ) continue ;

        // E -> F
        if ( stack_tbl.ParseEF() )
        {
            // 先読み
            // このままループに戻ると +, - が Hit してしまう。
            // +, - より *, / を優先するため、
            // 先読みして *, / がある場合は command_stack に積む。姑息ぅ
            if ( i<size )
            {
                if ( in_cmd[i] == '*'
                  || in_cmd[i] == '/'
                   )
                {
                    stack_tbl.CommandPush( in_cmd[i] ) ;
                    for ( ++i ; in_cmd[i] == ' ' ; ) ++i ;
                }
            }

            continue ;
        }

        // 次のコマンド
        if ( i<size )
        {
            stack_tbl.CommandPush( in_cmd[i] ) ;
            for ( ++i ; in_cmd[i] == ' ' ; ) ++i ;

            continue ;
        }

        break ;
    }

    return  stack_tbl.Interpret() ; // 実行
}

int main()
{
    printf( "%d\n", interpret( "+" ) ) ;
    printf( "syntax error\n" ) ;

    printf( "%d\n", interpret( "1" ) ) ;
    printf( "%d\n",             1    ) ;

    printf( "%d\n", interpret( "1 + 2 * 3" ) ) ;
    printf( "%d\n",             1 + 2 * 3    ) ;

    printf( "%d\n", interpret( "1 + 2 + 3 + 4" ) ) ;
    printf( "%d\n",             1 + 2 + 3 + 4    ) ;

    printf( "%d\n", interpret( "1 - 2 - 3 - 4" ) ) ;
    printf( "%d\n",             1 - 2 - 3 - 4    ) ;

    printf( "%d\n", interpret( "1 + 2 - 3 + 4" ) ) ;
    printf( "%d\n",             1 + 2 - 3 + 4    ) ;

    printf( "%d\n", interpret( "1 + 2 * 3 + 4" ) ) ;
    printf( "%d\n",             1 + 2 * 3 + 4    ) ;

    printf( "%d\n", interpret( "1 * 2 + 3 * 4" ) ) ;
    printf( "%d\n",             1 * 2 + 3 * 4    ) ;

    printf( "%d\n", interpret( "2 * 3 * 4 * 5" ) ) ;
    printf( "%d\n",             2 * 3 * 4 * 5    ) ;

    printf( "%d\n", interpret( "9 / 3 / 2" ) ) ;
    printf( "%d\n",             9 / 3 / 2    ) ;

    printf( "%d\n", interpret( "3 * 9 / 6" ) ) ;
    printf( "%d\n",             3 * 9 / 6    ) ;

    return  0 ;
}

/* 実行結果
command_stack: 
command_stack: +, 
syntax error
0
syntax error
command_stack: 
command_stack: 1, 
syntax trace : value 1
command_stack: F, 
command_stack: E, 
1
1
command_stack: 
command_stack: 1, 
syntax trace : value 1
command_stack: F, 
command_stack: E, 
command_stack: E, +, 
command_stack: E, +, 2, 
syntax trace : value 2
command_stack: E, +, F, 
command_stack: E, +, E, *, 
command_stack: E, +, E, *, 3, 
syntax trace : value 3
command_stack: E, +, E, *, F, 
syntax trace : 'E -> E * F'
command_stack: E, +, E, 
syntax trace : 'E -> E + E'
command_stack: E, 
interpret trace: 6 = 2 * 3
interpret trace: 7 = 1 + 6
7
7
command_stack: 
command_stack: 1, 
syntax trace : value 1
command_stack: F, 
command_stack: E, 
command_stack: E, +, 
command_stack: E, +, 2, 
syntax trace : value 2
command_stack: E, +, F, 
command_stack: E, +, E, 
syntax trace : 'E -> E + E'
command_stack: E, 
command_stack: E, +, 
command_stack: E, +, 3, 
syntax trace : value 3
command_stack: E, +, F, 
command_stack: E, +, E, 
syntax trace : 'E -> E + E'
command_stack: E, 
command_stack: E, +, 
command_stack: E, +, 4, 
syntax trace : value 4
command_stack: E, +, F, 
command_stack: E, +, E, 
syntax trace : 'E -> E + E'
command_stack: E, 
interpret trace: 3 = 1 + 2
interpret trace: 6 = 3 + 3
interpret trace: 10 = 6 + 4
10
10
command_stack: 
command_stack: 1, 
syntax trace : value 1
command_stack: F, 
command_stack: E, 
command_stack: E, -, 
command_stack: E, -, 2, 
syntax trace : value 2
command_stack: E, -, F, 
command_stack: E, -, E, 
syntax trace : 'E -> E - E'
command_stack: E, 
command_stack: E, -, 
command_stack: E, -, 3, 
syntax trace : value 3
command_stack: E, -, F, 
command_stack: E, -, E, 
syntax trace : 'E -> E - E'
command_stack: E, 
command_stack: E, -, 
command_stack: E, -, 4, 
syntax trace : value 4
command_stack: E, -, F, 
command_stack: E, -, E, 
syntax trace : 'E -> E - E'
command_stack: E, 
interpret trace: -1 = 1 - 2
interpret trace: -4 = -1 - 3
interpret trace: -8 = -4 - 4
-8
-8
command_stack: 
command_stack: 1, 
syntax trace : value 1
command_stack: F, 
command_stack: E, 
command_stack: E, +, 
command_stack: E, +, 2, 
syntax trace : value 2
command_stack: E, +, F, 
command_stack: E, +, E, 
syntax trace : 'E -> E + E'
command_stack: E, 
command_stack: E, -, 
command_stack: E, -, 3, 
syntax trace : value 3
command_stack: E, -, F, 
command_stack: E, -, E, 
syntax trace : 'E -> E - E'
command_stack: E, 
command_stack: E, +, 
command_stack: E, +, 4, 
syntax trace : value 4
command_stack: E, +, F, 
command_stack: E, +, E, 
syntax trace : 'E -> E + E'
command_stack: E, 
interpret trace: 3 = 1 + 2
interpret trace: 0 = 3 - 3
interpret trace: 4 = 0 + 4
4
4
command_stack: 
command_stack: 1, 
syntax trace : value 1
command_stack: F, 
command_stack: E, 
command_stack: E, +, 
command_stack: E, +, 2, 
syntax trace : value 2
command_stack: E, +, F, 
command_stack: E, +, E, *, 
command_stack: E, +, E, *, 3, 
syntax trace : value 3
command_stack: E, +, E, *, F, 
syntax trace : 'E -> E * F'
command_stack: E, +, E, 
syntax trace : 'E -> E + E'
command_stack: E, 
command_stack: E, +, 
command_stack: E, +, 4, 
syntax trace : value 4
command_stack: E, +, F, 
command_stack: E, +, E, 
syntax trace : 'E -> E + E'
command_stack: E, 
interpret trace: 6 = 2 * 3
interpret trace: 7 = 1 + 6
interpret trace: 11 = 7 + 4
11
11
command_stack: 
command_stack: 1, 
syntax trace : value 1
command_stack: F, 
command_stack: E, *, 
command_stack: E, *, 2, 
syntax trace : value 2
command_stack: E, *, F, 
syntax trace : 'E -> E * F'
command_stack: E, 
command_stack: E, +, 
command_stack: E, +, 3, 
syntax trace : value 3
command_stack: E, +, F, 
command_stack: E, +, E, *, 
command_stack: E, +, E, *, 4, 
syntax trace : value 4
command_stack: E, +, E, *, F, 
syntax trace : 'E -> E * F'
command_stack: E, +, E, 
syntax trace : 'E -> E + E'
command_stack: E, 
interpret trace: 2 = 1 * 2
interpret trace: 12 = 3 * 4
interpret trace: 14 = 2 + 12
14
14
command_stack: 
command_stack: 2, 
syntax trace : value 2
command_stack: F, 
command_stack: E, *, 
command_stack: E, *, 3, 
syntax trace : value 3
command_stack: E, *, F, 
syntax trace : 'E -> E * F'
command_stack: E, 
command_stack: E, *, 
command_stack: E, *, 4, 
syntax trace : value 4
command_stack: E, *, F, 
syntax trace : 'E -> E * F'
command_stack: E, 
command_stack: E, *, 
command_stack: E, *, 5, 
syntax trace : value 5
command_stack: E, *, F, 
syntax trace : 'E -> E * F'
command_stack: E, 
interpret trace: 6 = 2 * 3
interpret trace: 24 = 6 * 4
interpret trace: 120 = 24 * 5
120
120
command_stack: 
command_stack: 9, 
syntax trace : value 9
command_stack: F, 
command_stack: E, /, 
command_stack: E, /, 3, 
syntax trace : value 3
command_stack: E, /, F, 
syntax trace : 'E -> E / F'
command_stack: E, 
command_stack: E, /, 
command_stack: E, /, 2, 
syntax trace : value 2
command_stack: E, /, F, 
syntax trace : 'E -> E / F'
command_stack: E, 
interpret trace: 3 = 9 / 3
interpret trace: 1 = 3 / 2
1
1
command_stack: 
command_stack: 3, 
syntax trace : value 3
command_stack: F, 
command_stack: E, *, 
command_stack: E, *, 9, 
syntax trace : value 9
command_stack: E, *, F, 
syntax trace : 'E -> E * F'
command_stack: E, 
command_stack: E, /, 
command_stack: E, /, 6, 
syntax trace : value 6
command_stack: E, /, F, 
syntax trace : 'E -> E / F'
command_stack: E, 
interpret trace: 27 = 3 * 9
interpret trace: 4 = 27 / 6
4
4
Press any key to continue
*/

[振る舞い] Iterator パターン
STL にあるので詳細は省略。要するに、ポインタのような動作をするモノ。
#include <stdio.h> // puts()

#ifdef WIN32
#ifdef _DEBUG

  // VC++6.0 だと std::string と std::vector を一緒に使うと
  // warning がでる。ので抑止。ったく。
  #pragma warning( disable : 4786 )

#endif // _DEBUG
#endif // WIN32

#include <string>  // STL std::string
#include <vector>  // STL std::vector<>

// Iterator パターン

class IteratorObject
{} ;

class IteratorPtn
{
    virtual IteratorObject * Iterator() = 0 ; // イテレータ取得
    virtual IteratorObject * Next() = 0 ;     // 次
} ;

// 実装

class Fruit : public IteratorObject
{
public :
    std::string  m_name ; // 名前

    Fruit( std::string  in )
    : m_name( in )
    {}
} ;

class Kato : public IteratorPtn
{
#define TBL_MAX 10

    IteratorObject *   m_tbl[TBL_MAX] ;
    int                m_tbl_size ;
    int                m_point ;

public:
    Kato()
    {
        m_tbl_size = 0 ;
        m_point    = 0 ;
    }

    ~Kato()
    {
        for ( int i=0 ; i<m_tbl_size ; ++i )
        {
            delete m_tbl[i] ; // new したら delete する^^;
        }
    }

    void Have( IteratorObject * in )
    {
        if ( m_tbl_size < TBL_MAX )
        {
            m_tbl[m_tbl_size++] = in ; // テーブルに追加
        }
    }

    virtual IteratorObject *  Iterator() // イテレータ取得
    {
        m_point = 0 ;
        return  Next() ;
    }

    virtual IteratorObject *  Next() // 次
    {
        if ( m_point < m_tbl_size )
        {
            return m_tbl[m_point++] ;
        }
        return  0 ;
    }

#undef TBL_MAX
} ;

int main()
{
    // 自作イテレータ
    {
        Kato  ai ; // 誰?

        ai.Have( new Fruit( "Apple"  ) ) ;
        ai.Have( new Fruit( "Banana" ) ) ;
        ai.Have( new Fruit( "Cacao"  ) ) ;

        // こんな感じに使うのがミソ。
        IteratorObject *  it = ai.Iterator() ;
        for ( ; it != 0 ; it = ai.Next() )
        {
            puts( ((Fruit*)it)->m_name.c_str() ) ;
        }
    }

    //---------------------
    // STL なら簡単なのにねー。

    std::vector< std::string >  ryoko ; // だからぁ誰?

    ryoko.push_back( "Apple"  ) ;
    ryoko.push_back( "Banana" ) ;
    ryoko.push_back( "Cacao"  ) ;

    // STLでのイテレータ
    puts( "------" ) ;
    {
        std::vector< std::string >::iterator  it = ryoko.begin() ;

        for ( ; it != ryoko.end() ; ++it )
        {
            puts( it->c_str() ) ;
        }
    }

    // 個人的には(ランダムアクセス可能な)こっちの使い方が好み。
    // でも、これはイテレータとは言わないらしい。^^;
    puts( "------" ) ;
    {
        const int tbl_max = ryoko.size() ;

        for ( int i=0 ; i<tbl_max ; ++i )
        {
            puts( ryoko[i].c_str() ) ;
        }
    }

    return 0 ;
}
/* 実行結果
Apple
Banana
Cacao
------
Apple
Banana
Cacao
------
Apple
Banana
Cacao
Press any key to continue
*/

[振る舞い] Mediator パターン
ML(メイリングリスト)のようなイメージ。まとめ者のいるパターン。
#include <stdio.h> // printf()
#include <string>  // STL  std::string

// Mediator パターン

class MediatorPtn  // 相談役/調停者/まとめ者
{
public:
    virtual void  MessagePut( const std::string & in_str ) = 0 ;
} ;

class MemberPtn    // 各メンバー
{
public :
    MediatorPtn *  m_mediator ; // まとめ者
    virtual void  MessageGet( const std::string & in_str ) = 0 ;
} ;

// メンバーの実装

class Apple : public MemberPtn
{
public:
    virtual void MessageGet( const std::string & in_str )
    {
        if ( in_str == "リンゴ" )
        {
            puts( "リンゴと言えば…バ、ナ、ナ" ) ;
            m_mediator->MessagePut( "バナナ" ) ; // まとめ者に通達
        }
    }
} ;

class Banana : public MemberPtn
{
public:
    virtual void MessageGet( const std::string & in_str )
    {
        if ( in_str == "バナナ" )
        {
            puts( "バナナと言えば…カ、カ、オ" ) ;
            m_mediator->MessagePut( "カカオ" ) ; // まとめ者に通達
        }
    }
} ;

class Cacao : public MemberPtn
{
public:
    virtual void MessageGet( const std::string & in_str )
    {
        if ( in_str == "カカオ" )
        {
            puts( "カカオと言えば…リ、ン、ゴ" ) ;
            m_mediator->MessagePut( "リンゴ" ) ; // まとめ者に通達
        }
    }
} ;

// まとめ者の実装

class Hirosue : public MediatorPtn
{
    std::string  m_message ;  // 通達メッセージ

    // 支配下のメンバを登録(ホントは MemberPtn のテーブルにしたいね)
    Apple   m_apple ;
    Banana  m_banana ;
    Cacao   m_cacao ;

public:
    Hirosue()
    {
        m_message = "リンゴ" ; // リンゴからスタート

        m_apple.m_mediator  = this ; // まとめ者は Hirosue
        m_banana.m_mediator = this ; // まとめ者は Hirosue
        m_cacao.m_mediator  = this ; // まとめ者は Hirosue
    }

    // 意見を収集
    virtual void  MessagePut( const std::string & in_str )
    {
        m_message = in_str ;
    }

    // みんなに通知
    void  Notice()
    {
        std::string  str = m_message ;

        m_apple.MessageGet( str ) ;
        m_banana.MessageGet( str ) ;
        m_cacao.MessageGet( str ) ;
    }
} ;


int main()
{
    Hirosue  ryoko ; // まとめ者

    for (int i=0 ; i<7 ; ++i )
    {
        ryoko.Notice() ; // みんなに通知
    }

    return  0 ;
}

/* 実行結果
リンゴと言えば…バ、ナ、ナ
バナナと言えば…カ、カ、オ
カカオと言えば…リ、ン、ゴ
リンゴと言えば…バ、ナ、ナ
バナナと言えば…カ、カ、オ
カカオと言えば…リ、ン、ゴ
リンゴと言えば…バ、ナ、ナ
Press any key to continue
*/

[振る舞い] Mediator パターン(非継承版)
ML(メイリングリスト)のようなイメージ。まとめ者のいるパターン。
#include <stdio.h> // printf()
#include <string>  // STL  std::string

// メンバーの実装

templateclass _MediatorPtn >
class Apple
{
public:
    _MediatorPtn *  m_mediator ; // まとめ者

    void MessageGet( const std::string & in_str )
    {
        if ( in_str == "リンゴ" )
        {
            puts( "リンゴと言えば…バ、ナ、ナ" ) ;
            m_mediator->MessagePut( "バナナ" ) ; // まとめ者に通達
        }
    }
} ;

templateclass _MediatorPtn >
class Banana
{
public:
    _MediatorPtn *  m_mediator ; // まとめ者

    void MessageGet( const std::string & in_str )
    {
        if ( in_str == "バナナ" )
        {
            puts( "バナナと言えば…カ、カ、オ" ) ;
            m_mediator->MessagePut( "カカオ" ) ; // まとめ者に通達
        }
    }
} ;

templateclass _MediatorPtn >
class Cacao
{
public:
    _MediatorPtn *  m_mediator ; // まとめ者

    void MessageGet( const std::string & in_str )
    {
        if ( in_str == "カカオ" )
        {
            puts( "カカオと言えば…リ、ン、ゴ" ) ;
            m_mediator->MessagePut( "リンゴ" ) ; // まとめ者に通達
        }
    }
} ;

// まとめ者の実装

class Hirosue
{
    std::string  m_message ;  // 通達メッセージ

    // 支配下のメンバを登録(ホントはテーブルにしたいね)
    Apple< Hirosue >   m_apple ;
    Banana< Hirosue >  m_banana ;
    Cacao< Hirosue >   m_cacao ;

public:
    Hirosue()
    {
        m_message = "リンゴ" ; // リンゴからスタート

        m_apple.m_mediator  = this ; // まとめ者は Hirosue
        m_banana.m_mediator = this ; // まとめ者は Hirosue
        m_cacao.m_mediator  = this ; // まとめ者は Hirosue
    }

    // 意見を収集
    void  MessagePut( const std::string & in_str )
    {
        m_message = in_str ;
    }

    // みんなに通知
    void  Notice()
    {
        std::string  str = m_message ;

        m_apple.MessageGet( str ) ;
        m_banana.MessageGet( str ) ;
        m_cacao.MessageGet( str ) ;
    }
} ;


int main()
{
    Hirosue  ryoko ; // まとめ者

    for (int i=0 ; i<7 ; ++i )
    {
        ryoko.Notice() ; // みんなに通知
    }

    return  0 ;
}

/* 実行結果
リンゴと言えば…バ、ナ、ナ
バナナと言えば…カ、カ、オ
カカオと言えば…リ、ン、ゴ
リンゴと言えば…バ、ナ、ナ
バナナと言えば…カ、カ、オ
カカオと言えば…リ、ン、ゴ
リンゴと言えば…バ、ナ、ナ
Press any key to continue
*/

[振る舞い] Memento パターン(非継承版)
継承するまでもないよね。
ステータス情報をセーブしたりロードしたりするパターン。
#include <stdio.h>  // printf()
#include <stdlib.h> // rand()
#include <vector>   // STL  std::vector<>

// Memento パターンだけど、パターンと言うのかな?

class Memento       // 保存情報(ステータス)
{
    friend class Hirosue ; // 値が見れる/触れるのは Hirosue だけ。

    int  m_weight  ; // 体重
} ;

class Hirosue
{
#define START_KG 43
public :
    Memento  m_stat ; // 保存情報(ステータス)

    Hirosue()
    {
        m_stat.m_weight = START_KG ; // Kg
    }

    int  Diet()
    {
        int apple  = 1 + rand() % 5 ; // リンゴ
        int banana = 1 + rand() % 5 ; // バナナ

        m_stat.m_weight += banana - apple ; // バナナは増えるリンゴは減る
        printf( "リンゴ%2d個、バナナ%2d本 -> %3d Kg\n",
            apple, banana, m_stat.m_weight
        ) ;

        return  m_stat.m_weight - START_KG ; // どのくらい変化したか?
    }
#undef START_KG
} ;

int main()
{
    std::vector< Memento >  m_save_tbl ; // 過去の記録

    Hirosue  ryoko ;

    for ( int i=0 ; i<10 ; ++i )
    {
        // 今の状態を保存
        m_save_tbl.push_back( ryoko.m_stat ) ;

        int w = ryoko.Diet() ;

        if ( w < -2 ) // 3Kg減
        {
            puts( "やせ過ぎ、1つ前に戻す。" ) ;
            ryoko.m_stat = m_save_tbl.back() ;

            continue ;
        }
        if ( w > 2 ) // 3Kg増
        {
            puts( "太り過ぎ、1つ前に戻す。" ) ;
            ryoko.m_stat = m_save_tbl.back() ;

            continue ;
        }
    }
    return  0 ;
}


/* 実行結果
リンゴ 2個、バナナ 3本 ->  44 Kg
リンゴ 5個、バナナ 1本 ->  40 Kg
やせ過ぎ、1つ前に戻す。
リンゴ 5個、バナナ 5本 ->  44 Kg
リンゴ 4個、バナナ 4本 ->  44 Kg
リンゴ 3個、バナナ 5本 ->  46 Kg
太り過ぎ、1つ前に戻す。
リンゴ 1個、バナナ 1本 ->  44 Kg
リンゴ 2個、バナナ 3本 ->  45 Kg
リンゴ 2個、バナナ 2本 ->  45 Kg
リンゴ 1個、バナナ 3本 ->  47 Kg
太り過ぎ、1つ前に戻す。
リンゴ 3個、バナナ 2本 ->  44 Kg
Press any key to continue
*/

[振る舞い] Observer パターン
ドキュメント(データ)が更新された時、関連するビュー(観察者)に知らされるパターン。
#include <stdio.h>  // printf()
#include <stdlib.h> // rand()

// Observer パターン(観察者)

class ObserverPtn
{
public:
    virtual void  Update( int in_n ) = 0 ;
} ;

// 実装

class Apple : public ObserverPtn
{
public:
    virtual void  Update( int in_n ) // 知らせを受ける
    {
        printf( "リンゴなら %d 個やな。\n", in_n / 120 ) ;
    }
} ;

class Banana : public ObserverPtn
{
public:
    virtual void  Update( int in_n ) // 知らせを受ける
    {
        printf( "バナナなら %d 本、買えまっせ〜\n", in_n / 60 ) ;
    }
} ;

class Honjyo
{
#define TBL_MAX 8
    ObserverPtn *  m_tbl[TBL_MAX] ;
    int            m_tbl_size ;

    int            m_value ;

public:
    Honjyo()
    : m_tbl_size( 0 )
    , m_value( 0 )
    {}

public:
    void  Attach( ObserverPtn* in ) // 観察者を登録
    {
        if ( m_tbl_size < TBL_MAX )
        {
            m_tbl[m_tbl_size++] = in ;
        }
    }

public:
    void  DoSomething()
    {
        if ( (rand()%2) == 0 )
        {
            // 変化あり
            // お小遣いGet!!(200円まで)
            m_value += rand() % 200 ;
            printf( "お小遣い %d 円!\n", m_value ) ;

            // みんな(観察者)に知らせる
            for ( int i=0 ; i<m_tbl_size ; ++i )
            {
                m_tbl[i]->Update( m_value ) ;
            }
        }
        else
        {
            // 変化なし
            puts( "ひまやな〜" ) ;
        }
    }
#undef TBL_MAX
} ;


int main()
{
    Honjyo  manami ;      // 観察される人

    Apple   apple_shop ;  // 観察する人?
    Banana  banana_shop ; // 観察する人?

    manami.Attach( & apple_shop ) ;
    manami.Attach( & banana_shop ) ;
    
    for ( int i=0 ; i<8 ; ++i )
    {
        manami.DoSomething() ;
    }

    return  0 ;
}

/* 実行結果
ひまやな〜
ひまやな〜
お小遣い 100 円!
リンゴなら 0 個やな。
バナナなら 1 本、買えまっせ〜
ひまやな〜
お小遣い 178 円!
リンゴなら 1 個やな。
バナナなら 2 本、買えまっせ〜
お小遣い 340 円!
リンゴなら 2 個やな。
バナナなら 5 本、買えまっせ〜
お小遣い 445 円!
リンゴなら 3 個やな。
バナナなら 7 本、買えまっせ〜
ひまやな〜
Press any key to continue
*/

[振る舞い] Observer パターン (非継承版)
ドキュメント(データ)が更新された時、関連するビュー(観察者)に知らされるパターン。
#include <stdio.h>  // printf()
#include <stdlib.h> // rand()

// Observer パターン(観察者)
// 実装

class Apple
{
public:
    void  Update( int in_n ) // 知らせを受ける
    {
        printf( "リンゴなら %d 個やな。\n", in_n / 120 ) ;
    }
} ;

class Banana
{
public:
    void  Update( int in_n ) // 知らせを受ける
    {
        printf( "バナナなら %d 本、買えまっせ〜\n", in_n / 60 ) ;
    }
} ;

templateclass _ObserverPtn1, class _ObserverPtn2 >
class Honjyo
{
    // ホントはテーブルにしたいけど、template では無理だね。
    _ObserverPtn1 &  m_observer1 ;
    _ObserverPtn2 &  m_observer2 ;

    int              m_value ;

public:
    Honjyo( _ObserverPtn1 & in1, _ObserverPtn2 & in2 ) // 観察者
    : m_observer1( in1 )
    , m_observer2( in2 )
    , m_value( 0 )
    {}

    void  DoSomething()
    {
        if ( (rand()%2) == 0 )
        {
            // 変化あり
            // お小遣いGet!!(200円まで)
            m_value += rand() % 200 ;
            printf( "お小遣い %d 円!\n", m_value ) ;

            // みんな(観察者)に知らせる
            m_observer1.Update( m_value ) ;
            m_observer2.Update( m_value ) ;
        }
        else
        {
            // 変化なし
            puts( "ひまやな〜" ) ;
        }
    }
} ;


int main()
{
    Apple   apple_shop ;  // 観察する人?
    Banana  banana_shop ; // 観察する人?

    // 観察される人
    Honjyo< Apple, Banana >  manami( apple_shop, banana_shop ) ;

    for ( int i=0 ; i<8 ; ++i )
    {
        manami.DoSomething() ;
    }

    return  0 ;
}

/* 実行結果
ひまやな〜
ひまやな〜
お小遣い 100 円!
リンゴなら 0 個やな。
バナナなら 1 本、買えまっせ〜
ひまやな〜
お小遣い 178 円!
リンゴなら 1 個やな。
バナナなら 2 本、買えまっせ〜
お小遣い 340 円!
リンゴなら 2 個やな。
バナナなら 5 本、買えまっせ〜
お小遣い 445 円!
リンゴなら 3 個やな。
バナナなら 7 本、買えまっせ〜
ひまやな〜
Press any key to continue
*/


[振る舞い] State パターン
状態をインスタンスにするパターン。継承を使う最も簡単な例ともいえる。

他の似ているパターンの微妙な違い
TemplateMethod : 静的な拡張(ルーチンの共通化)が目的
Strategy : 入れ替え可能な状態として作りこむのが目的
* State : 頻繁に入れ替えるのが主な目的
#include <stdio.h>  // puts()
#include <stdlib.h> // rand()

// Stateパターン

class StatePtn
{
public:
    virtual void  Eat() = 0 ; // 食べる(共通動作)
} ;

// 実装

class Apple : public StatePtn
{
public:
    virtual void  Eat()
    {
        puts( "リンゴ大好き!。パクパク。" ) ;
    }
} ;

class Banana : public StatePtn
{
public:
    virtual void  Eat()
    {
        puts( "バナナおいしいね。ムシャムシャ。" ) ;
    }
} ;

class Hirosue
{
    StatePtn *  m_stat ; // 状態、1つしか持たない。

public:
    Hirosue()
    : m_stat( 0 )
    {}

public:
    void  Have( StatePtn * in )
    {
        m_stat = in ;
    }

public:
    void  DoSomething()
    {
        // なにかをする。(状態によってなにをするのかが変わる)
        if ( m_stat != 0 )  m_stat->Eat() ; // 持っているモノを食べる
        else puts( "なにも持ってませーん。" ) ;
    }
} ;

int main()
{
    Apple   apple ;
    Banana  banana ;

    Hirosue  ryoko ;

    for ( int i=0 ; i<10 ; ++i )
    {
        // 乱数で行動を決定
        int r = rand() % 4 ;

        printf( "%d : %d ", i, r ) ;
        switch ( r )
        {
        case 0 :
            ryoko.Have( & apple ) ;
            puts( "リンゴをもらいました。" ) ;
            break ;
        case 1 :
            ryoko.Have( & banana ) ;
            puts( "バナナをもらいました。" ) ;
            break ;
        case 2 :
            ryoko.DoSomething() ; // なにかをする
            break ;
        default:
            puts( "ひまですぅ" ) ; // なにもしない
            break ;
        }
        // end switch r
    }
    // end for i

    return  0 ;
}

/* 実行結果
0 : 1 バナナをもらいました。
1 : 3 ひまですぅ
2 : 2 バナナおいしいね。ムシャムシャ。
3 : 0 リンゴをもらいました。
4 : 1 バナナをもらいました。
5 : 0 リンゴをもらいました。
6 : 2 リンゴ大好き!。パクパク。
7 : 2 リンゴ大好き!。パクパク。
8 : 2 リンゴ大好き!。パクパク。
9 : 0 リンゴをもらいました。
Press any key to continue
*/

[振る舞い] State パターン(非継承版)
状態をインスタンスにするパターン。
template では入れ替えは難しいですね。できないことはないけどいまいちです。

他の似ているパターンの微妙な違い
TemplateMethod : 静的な拡張(ルーチンの共通化)が目的
Strategy : 入れ替え可能な状態として作りこむのが目的
* State : 頻繁に入れ替えるのが主な目的
#include <stdio.h>  // puts()
#include <stdlib.h> // rand()

// Stateパターン

// 実装

class Apple 
{
public:
    void  Eat()
    {
        puts( "リンゴ大好き!。パクパク。" ) ;
    }
} ;

class Banana
{
public:
    void  Eat()
    {
        puts( "バナナおいしいね。ムシャムシャ。" ) ;
    }
} ;

enum STAT { NOTHING, APPLE, BANANA, } ;

templateclass _StatA, class _StatB >
class Hirosue
{
    enum STAT  m_stat ; // 状態、1つしか持たない。
    _StatA &   m_a ;
    _StatB &   m_b ;

public:
    Hirosue(
        _StatA &  in_a,
        _StatB &  in_b
    )
    : m_stat( NOTHING )
    , m_a( in_a )
    , m_b( in_b )
    {}

public:
    void  Have( const enum STAT & in )
    {
        m_stat = in ;
    }

public:
    void  DoSomething()
    {
        // なにかをする。(状態によってなにをするのかが変わる)

        // このパターンはすなおに継承版を使うべきかも。
        // switch を使うといまいち。
        switch ( m_stat )
        {
            case APPLE  : m_a.Eat() ; break ;
            case BANANA : m_b.Eat() ; break ;
            default     : puts( "なにも持ってませーん。" ) ; break ;
        }
    }
} ;

int main()
{
    Apple    apple ;
    Banana   banana ;

    Hirosue< Apple, Banana >  ryoko( apple, banana ) ;

    for ( int i=0 ; i<10 ; ++i )
    {
        // 乱数で行動を決定
        int r = rand() % 4 ;

        printf( "%d : %d ", i, r ) ;
        switch ( r )
        {
        case 0 :
            ryoko.Have( APPLE ) ;
            puts( "リンゴをもらいました。" ) ;
            break ;
        case 1 :
            ryoko.Have( BANANA ) ;
            puts( "バナナをもらいました。" ) ;
            break ;
        case 2 :
            ryoko.DoSomething() ; // なにかをする
            break ;
        default:
            puts( "ひまですぅ" ) ; // なにもしない
            break ;
        }
        // end switch r
    }
    // end for i

    return  0 ;
}

/* 実行結果
0 : 1 バナナをもらいました。
1 : 3 ひまですぅ
2 : 2 バナナおいしいね。ムシャムシャ。
3 : 0 リンゴをもらいました。
4 : 1 バナナをもらいました。
5 : 0 リンゴをもらいました。
6 : 2 リンゴ大好き!。パクパク。
7 : 2 リンゴ大好き!。パクパク。
8 : 2 リンゴ大好き!。パクパク。
9 : 0 リンゴをもらいました。
Press any key to continue
*/

[振る舞い] Strategy パターン
戦略を考える「頭脳(アルゴリズム)」を入れ替えるパターン

他の似ているパターンの微妙な違い
TemplateMethod : 静的な拡張(ルーチンの共通化)が目的
* Strategy : 入れ替え可能な状態として作りこむのが目的
State : 頻繁に入れ替えるのが主な目的
#include <stdio.h> // puts()

// Strategy パターン?

enum COLOR { RED, BLUE, YELLOW, } ; // 色
enum SHAPE { BALL, BOX, COLUMN, } ; // 形

class StrategyPtn
{
public:
    virtual char *  FinalAnswer(
        enum COLOR  in_color, // 色
        enum SHAPE  in_shape  // 形
    ) = 0 ;
} ;

// 実装

class Hirosue : public StrategyPtn // 戦略アルゴリズム
{
public:
    virtual char *  FinalAnswer(
        enum COLOR  in_color,  // 色
        enum SHAPE  in_shape   // 形
    )
    {
        // ホントはいろいろ複雑な計算をしていると思われ

        if ( in_shape == BALL ) return "これはリンゴかな?" ;
        else                    return "たぶんバナナでしょ" ;
    }
} ;

class Honjyo : public StrategyPtn // 戦略アルゴリズム
{
public:
    virtual char *  FinalAnswer(
        enum COLOR  in_color,  // 色
        enum SHAPE  in_shape   // 形
    )
    {
        // ホントはいろいろ複雑な計算をしていると思われ

        if ( in_color == RED ) return "赤いのはリンゴや" ;
        else                   return "他の色はバナナや" ;
    }
} ;

class Apple
{
    StrategyPtn *  m_strategy ; // 戦略アルゴリズム

public:
    // ↓切り替え可能( Stateパターンほど頻繁に切り替えるわけではない)
    Apple( StrategyPtn *  in_strategy )
    {
        m_strategy = in_strategy ;
    }

    void  Answer_Put()
    {
        puts( m_strategy->FinalAnswer( RED, BALL ) ) ;
    }
} ;

class Banana
{
    StrategyPtn *  m_strategy ;

public:
    Banana( StrategyPtn *  in_strategy ) // <- 切り替え可能 
    {
        m_strategy = in_strategy ;
    }

    void  Answer_Put()
    {
        puts( m_strategy->FinalAnswer( YELLOW, COLUMN ) ) ;
    }
} ;

int main()
{
    Hirosue  ryoko ;
    Honjyo   manami ;
    {
        Apple   apple( & ryoko ) ;
        Banana  banana( & manami ) ;

        apple.Answer_Put() ;
        banana.Answer_Put() ;
    }
    {
        Apple   apple( & manami ) ;
        Banana  banana( & ryoko ) ;

        apple.Answer_Put() ;
        banana.Answer_Put() ;
    }

    return  0 ;
}

/* 実行結果
これはリンゴかな?
他の色はバナナや
赤いのはリンゴや
たぶんバナナでしょ
Press any key to continue
*/

[振る舞い] Strategy パターン (非継承版)
戦略を考える「頭脳(アルゴリズム)」を入れ替えるパターン

他の似ているパターンの微妙な違い
TemplateMethod : 静的な拡張(ルーチンの共通化)が目的
* Strategy : 入れ替え可能な状態として作りこむのが目的
State : 頻繁に入れ替えるのが主な目的
#include <stdio.h> // puts()

// 実装

enum COLOR { RED, BLUE, YELLOW, } ; // 色
enum SHAPE { BALL, BOX, COLUMN, } ; // 形

class Hirosue // 戦略アルゴリズム
{
public:
    char *  FinalAnswer(
        enum COLOR   in_color,  // 色
        enum SHAPE   in_shape   // 形
    )
    {
        // ホントはいろいろ複雑な計算をしていると思われ

        if ( in_shape == BALL ) return "これはリンゴかな?" ;
        else                    return "たぶんバナナでしょ" ;
    }
} ;

class Honjyo // 戦略アルゴリズム
{
public:
    char *  FinalAnswer(
        enum COLOR   in_color,  // 色
        enum SHAPE   in_shape   // 形
    )
    {
        // ホントはいろいろ複雑な計算をしていると思われ

        if ( in_color == RED ) return "赤いのはリンゴや" ;
        else                   return "他の色はバナナや" ;
    }
} ;

templateclass _StrategyPtn >
class Apple
{
    _StrategyPtn   m_strategy ; // 戦略アルゴリズム <- 切り替え可能

public:
    void  Answer_Put()
    {
        puts( m_strategy.FinalAnswer( RED, BALL ) ) ;
    }
} ;

templateclass _StrategyPtn >
class Banana
{
    _StrategyPtn  m_strategy ; // 戦略アルゴリズム <- 切り替え可能

public:
    void  Answer_Put()
    {
        puts( m_strategy.FinalAnswer( YELLOW, COLUMN ) ) ;
    }
} ;

int main()
{
    {
        Apple< Hirosue >  apple ;
        Banana< Honjyo >  banana ;

        apple.Answer_Put() ;
        banana.Answer_Put() ;
    }
    {
        Apple< Honjyo >    apple ;
        Banana< Hirosue >  banana ;

        apple.Answer_Put() ;
        banana.Answer_Put() ;
    }

    return  0 ;
}

/* 実行結果
これはリンゴかな?
他の色はバナナや
赤いのはリンゴや
たぶんバナナでしょ
Press any key to continue
*/

[振る舞い] TemplateMethod パターン
一部の機能を後で実装する。委譲ではなく、継承を使うのが TemplateMethod のパターン。
TemplateMethod というより SkeletonMethod と呼んだほうが良いよね。

他の似ているパターンの微妙な違い
* TemplateMethod : 静的な拡張(ルーチンの共通化)が目的
Strategy : 入れ替え可能な状態として作りこむのが目的
State : 頻繁に入れ替えるのが主な目的
#include <stdio.h> // printf()

// TemplateMethod パターン

class Kato
{
    // 後で実装(肉付け)するメソッド
    virtual char *  Name()  = 0 ; // <- 未実装
    virtual char *  Color() = 0 ; // <- 未実装

public:
    // 一部の機能は未実装のスケルトン(骨組み)メソッド
    void TemplateMethod()
    {
        printf( 
            "%s の色は %s ですネ。\n",
            Name(),  // <- 未実装
            Color()  // <- 未実装
        ) ;
    }
} ;

// 実装

class Apple : public Kato
{
    virtual char *  Name()  { return "リンゴ" ; } ;
    virtual char *  Color() { return "赤"     ; } ;
} ;

class Banana : public Kato
{
    virtual char *  Name()  { return "バナナ" ; } ;
    virtual char *  Color() { return "黄色"   ; } ;
} ;


int main()
{
    Apple   apple ;
    Banana  banana ;

    apple.TemplateMethod() ;
    banana.TemplateMethod() ;

    return  0 ;
}

/* 実行結果
リンゴ の色は 赤 ですネ。
バナナ の色は 黄色 ですネ。
Press any key to continue
*/

[振る舞い] TemplateMethod パターン (非継承版)
一部の機能を後で実装する。委譲ではなく、継承を使うのが TemplateMethod のパターン。
TemplateMethod というより SkeletonMethod と呼んだほうが良いよね。

他の似ているパターンの微妙な違い
* TemplateMethod : 静的な拡張(ルーチンの共通化)が目的
Strategy : 入れ替え可能な状態として作りこむのが目的
State : 頻繁に入れ替えるのが主な目的
#include <stdio.h> // printf()

// TemplateMethod パターン

templateclass _TemplateMethodPtn >
class Kato
{
    // 後で実装(肉付け)するメソッド
    _TemplateMethodPtn  m_object ;  // <- 未実装

public:
    // 一部の機能は未実装のスケルトン(骨組み)メソッド
    void  TemplateMethod()
    {
        printf( 
            "%s の色は %s ですネ。\n",
            m_object.Name(),  // <- 未実装
            m_object.Color()  // <- 未実装
        ) ;
    }
} ;


// 実装

class Apple
{
public:
    char *  Name()  { return "リンゴ" ; } ;
    char *  Color() { return "赤"     ; } ;
} ;

class Banana
{
public:
    char *  Name()  { return "バナナ" ; } ;
    char *  Color() { return "黄色"   ; } ;
} ;

int main()
{
    Kato< Apple >   apple ;
    Kato< Banana >  banana ;

    apple.TemplateMethod() ;
    banana.TemplateMethod() ;

    return 0 ;
}

/* 実行結果
リンゴ の色は 赤 ですネ。
バナナ の色は 黄色 ですネ。
Press any key to continue
*/

[振る舞い] Visitor パターン
訪れて処理するというパターン。
データ構造に依存しない処理構造を作るのが目的。
Composite パターンとの相性がいい。
#include <stdio.h> // printf()

// Visitorパターン

class AppleShop ;  // 具体的な店1
class BananaShop ; // 具体的な店2

class VisitorPtn   // 抽象的な訪問者
{
public:
    virtual void  Visit( AppleShop *  in_apple  ) = 0 ;
    virtual void  Visit( BananaShop * in_banana ) = 0 ;
} ;

class AcceptorPtn // 抽象的な店
{
public:
    virtual void  Accept( VisitorPtn * in_visitor ) = 0 ;
} ;

// 実装

// お店を実装

class AppleShop : public AcceptorPtn
{
public:
    virtual void  Accept( VisitorPtn* in_visitor )
    {
        in_visitor->Visit( this ) ;
    }
} ;

class BananaShop : public AcceptorPtn
{
public:
    virtual void  Accept( VisitorPtn* in_visitor )
    {
        in_visitor->Visit( this ) ;
    }
} ;

// お客さん(訪問者)を実装

class Hirosue : public VisitorPtn
{
public:
    virtual void  Visit( AppleShop *  in_apple )
    {
        puts( "リンゴは1つ下さいな。" ) ;
    }
public:
    virtual void  Visit( BananaShop *  in_banana )
    {
        puts( "バナナはいらないんです。" ) ;
    }
} ;

class Honjyo : public VisitorPtn
{
public:
    virtual void  Visit( AppleShop *  in_apple )
    {
        puts( "リンゴを2つくれへん?。" ) ;
    }
public:
    virtual void  Visit( BananaShop *  in_banana )
    {
        puts( "バナナはあるだけ全部もらっとくわ。" ) ;
    }
} ;

// 買い物する町を実装

int main()
{
    // お店4つ
    AcceptorPtn *  tbl[4] =
    {
        new AppleShop,
        new BananaShop,
        new AppleShop,
        new BananaShop,
    } ;

    // 2人が順番に4つの店に訪問する
    Hirosue  ryoko ;
    Honjyo   manami ;

    const int  tbl_size = sizeof(tbl)/sizeof(tbl[0]) ;
    { for ( int i=0 ; i<tbl_size ; ++ i )
    {
        tbl[i]->Accept( & ryoko ) ;
        tbl[i]->Accept( & manami ) ;
    }}

    // 店を閉める
    { for ( int i=0 ; i<tbl_size ; ++ i )
    {
        delete tbl[i] ;
    }}

    return  0 ;
}

/* 実行結果
リンゴは1つ下さいな。
リンゴを2つくれへん?。
バナナはいらないんです。
バナナはあるだけ全部もらっとくわ。
リンゴは1つ下さいな。
リンゴを2つくれへん?。
バナナはいらないんです。
バナナはあるだけ全部もらっとくわ。
Press any key to continue
*/

[振る舞い] Visitor パターン (非継承版)
訪れて処理するというパターン。
データ構造に依存しない処理構造を作るのが目的。
Composite パターンとの相性がいい。
#include <stdio.h> // printf()

// 実装

// お店を実装

class AppleShop
{
public:
    templateclass _VisitorPtn >
    void  Accept( _VisitorPtn & in_visitor )
    {
        in_visitor.Visit( this ) ;
    }
} ;

class BananaShop
{
public:
    templateclass _VisitorPtn >
    void  Accept( _VisitorPtn & in_visitor )
    {
        in_visitor.Visit( this ) ;
    }
} ;

// お客さん(訪問者)を実装

class Hirosue
{
public:
    void  Visit( AppleShop *  in_apple )
    {
        puts( "リンゴは1つ下さいな。" ) ;
    }
public:
    void  Visit( BananaShop *  in_banana )
    {
        puts( "バナナはいらないんです。" ) ;
    }
} ;

class Honjyo
{
public:
    void  Visit( AppleShop *  in_apple )
    {
        puts( "リンゴを2つくれへん?。" ) ;
    }
public:
    void  Visit( BananaShop *  in_banana )
    {
        puts( "バナナはあるだけ全部もらっとくわ。" ) ;
    }
} ;

// 買い物する町を実装

int main()
{
    // お店4つ(template だと、テーブルに出来ないのが悲しいね。)
    AppleShop   shop_1 ;
    BananaShop  shop_2 ;
    AppleShop   shop_3 ;
    BananaShop  shop_4 ;

    // 2人が順番に4つの店に訪問する
    Hirosue  ryoko ;
    Honjyo   manami ;

    // テーブルでないので、ループにもできない。
    // でも、構造は分かりやすくなっているかも。
    shop_1.Accept( ryoko ) ;  shop_1.Accept( manami ) ;
    shop_2.Accept( ryoko ) ;  shop_2.Accept( manami ) ;
    shop_3.Accept( ryoko ) ;  shop_3.Accept( manami ) ;
    shop_4.Accept( ryoko ) ;  shop_4.Accept( manami ) ;

    return  0 ;
}

/* 実行結果
リンゴは1つ下さいな。
リンゴを2つくれへん?。
バナナはいらないんです。
バナナはあるだけ全部もらっとくわ。
リンゴは1つ下さいな。
リンゴを2つくれへん?。
バナナはいらないんです。
バナナはあるだけ全部もらっとくわ。
Press any key to continue
*/

[生成] AbstractFactory パターン
抽象的な製品を作る抽象的な工場。
#include <stdio.h> // puts()

// AbstractFactory パターン

class ProductPtn // 抽象的な製品
{
public:
    virtual void  Name_Put() = 0 ; // 製品の共通機能
} ;

class AbstractFactoryPtn // 抽象的な工場
{
public:
    virtual ProductPtn *  Create()   = 0 ; // 製品の製造
    virtual void          Name_Put() = 0 ; // 工場の共通機能
} ;

// 具体的な製品を実装

class Apple : public ProductPtn
{
public:
    virtual void  Name_Put() // 製品の共通機能 
    {
        printf( "リンゴ" ) ;
    }
} ;

class Banana : public ProductPtn
{
public:
    virtual void  Name_Put() // 製品の共通機能 
    {
        printf( "バナナ" ) ;
    }
} ;

// 具体的な工場を実装

class AppleFactory : public AbstractFactoryPtn
{
public:
    virtual ProductPtn *  Create() // 製品の製造
    {
        return  new Apple ;
    }
public:
    virtual void  Name_Put() // 工場の共通機能 
    {
        printf( "リンゴ工場" ) ;
    }
} ;

class BananaFactory : public AbstractFactoryPtn
{
public:
    virtual ProductPtn *  Create() // 製品の製造
    {
        return  new Banana ;
    }
public:
    virtual void  Name_Put() // 工場の共通機能 
    {
        printf( "バナナ工場" ) ;
    }
} ;

// 製品や工場に対して抽象的なコードが書ける。
// 製品や工場の具体的な仕様を知らなくてもよい。

void sub( AbstractFactoryPtn * in_factory )
{
    printf( "「" ) ;
    in_factory->Name_Put() ;         // 工場の共通機能 
    printf( "」で作る製品は「" ) ;
    {
        ProductPtn *  fruit = in_factory->Create() ; // 製品の製造
        fruit->Name_Put() ;                          // 製品の共通機能 
        delete  fruit ;                              // 製品の破棄
    }
    printf( "」です。\n" ) ;
}

int main()
{
    AppleFactory   apple_factory ;  // リンゴ工場を作成
    BananaFactory  banana_factory ; // バナナ工場を作成

    sub( & apple_factory ) ;
    sub( & banana_factory ) ;

    return  0 ;
}

/* 実行結果
「リンゴ工場」で作る製品は「リンゴ」です。
「バナナ工場」で作る製品は「バナナ」です。
Press any key to continue
*/

[生成] AbstractFactory パターン (非継承版)
抽象的な製品を作る抽象的な工場。
#include <stdio.h> // puts()

// 具体的な製品を実装

class Apple
{
public:
    void  Name_Put() // 製品の共通機能 
    {
        printf( "リンゴ" ) ;
    }
} ;

class Banana
{
public:
    void  Name_Put() // 製品の共通機能 
    {
        printf( "バナナ" ) ;
    }
} ;

// 具体的な工場を実装

class AppleFactory
{
    Apple  m_apple ;
public:
    Apple &  Create() // 製品の製造
    {
        return  m_apple ;
    }
public:
    void  Name_Put() // 工場の共通機能 
    {
        printf( "リンゴ工場" ) ;
    }
} ;

class BananaFactory 
{
    Banana  m_banana ;
public:
    Banana &  Create() // 製品の製造
    {
        return  m_banana ;
    }
public:
    void  Name_Put() // 工場の共通機能 
    {
        printf( "バナナ工場" ) ;
    }
} ;

// 製品や工場に対して抽象的なコードが書ける。
// 製品や工場の具体的な仕様を知らなくてもよい。

templateclass _AbstractFactoryPtn >
void sub( _AbstractFactoryPtn &  in_factory )
{
    printf( "「" ) ;
    in_factory.Name_Put() ;              // 工場の共通機能 
    printf( "」で作る製品は「" ) ;
    {
        in_factory.Create().Name_Put() ; // 製品の製造&共通機能 
    }
    printf( "」です。\n" ) ;
}

int main()
{
    AppleFactory   apple_factory ;  // リンゴ工場を作成
    BananaFactory  banana_factory ; // バナナ工場を作成

    sub( apple_factory ) ;
    sub( banana_factory ) ;

    return  0 ;
}

/* 実行結果
「リンゴ工場」で作る製品は「リンゴ」です。
「バナナ工場」で作る製品は「バナナ」です。
Press any key to continue
*/

[生成] Builder パターン
生成過程を共通化できる。Facade パターンとも似ているが、こっちは生成過程に特化しているらしい。
#include <stdio.h> // puts()
#include <string>  // STL std::string

// Builder パターン

class BuilderPtn
{
public:
    std::string   m_result_str ; // 結果

    // 共通化された生成過程
    virtual void  Step1() = 0 ;
    virtual void  Step2() = 0 ;
    virtual void  Step3() = 0 ;
    virtual void  Step4() = 0 ;
} ;

// 実装

class Apple : public BuilderPtn
{
public:
    virtual void  Step1() { m_result_str += "リンゴを洗う\n" ;       }
    virtual void  Step2() { m_result_str += "ナイフで6つに切る\n" ; }
    virtual void  Step3() { m_result_str += "ナイフで皮をむく\n";    }
    virtual void  Step4() { m_result_str += "食べる「パクパク」" ;   }
} ;

class Banana : public BuilderPtn
{
public:
    virtual void  Step1() {} // 具体的な作業無し
    virtual void  Step2() {} // 具体的な作業無し
    virtual void  Step3() { m_result_str += "バナナの皮をむく\n" ;     }
    virtual void  Step4() { m_result_str += "食べる「ムシャムシャ」" ; }
} ;


void sub( BuilderPtn * in_builder )
{
    puts( "あー、おなかすいた。" ) ;

    // 生成過程を共通化できる。
    in_builder->Step1() ;
    in_builder->Step2() ;
    in_builder->Step3() ;
    in_builder->Step4() ;

    // 生成結果を表示
    puts( in_builder->m_result_str.c_str() ) ;

    puts( "あー、おいしかった。\n" ) ;
}

int main()
{
    Apple   apple ;
    Banana  banana ;

    sub( & apple ) ;
    sub( & banana ) ;

    return  0 ;
}

/* 実行結果
あー、おなかすいた。
リンゴを洗う
ナイフで6つに切る
ナイフで皮をむく
食べる「パクパク」
あー、おいしかった。

あー、おなかすいた。
バナナの皮をむく
食べる「ムシャムシャ」
あー、おいしかった。

Press any key to continue
*/

[生成] Builder パターン (非継承版)
生成過程を共通化できる。 Facade パターンとも似ているが、こっちは生成過程に特化しているらしい。
#include <stdio.h> // puts()
#include <string>  // STL std::string

// 実装

class Apple
{
public:
    std::string   m_result_str ; // 結果
    void  Step1() { m_result_str += "リンゴを洗う\n" ;       }
    void  Step2() { m_result_str += "ナイフで6つに切る\n" ; }
    void  Step3() { m_result_str += "ナイフで皮をむく\n";    }
    void  Step4() { m_result_str += "食べる「パクパク」" ;   }
} ;

class Banana
{
public:
    std::string   m_result_str ; // 結果
    void  Step1() {} // 具体的な作業無し
    void  Step2() {} // 具体的な作業無し
    void  Step3() { m_result_str += "バナナの皮をむく\n" ;     }
    void  Step4() { m_result_str += "食べる「ムシャムシャ」" ; }
} ;

templateclass _BuilderPtn >
void sub( _BuilderPtn &  in_builder )
{
    puts( "あー、おなかすいた。" ) ;

    // 生成過程を共通化できる。
    in_builder.Step1() ;
    in_builder.Step2() ;
    in_builder.Step3() ;
    in_builder.Step4() ;

    // 生成結果を表示
    puts( in_builder.m_result_str.c_str() ) ;

    puts( "あー、おいしかった。\n" ) ;
}

int main()
{
    Apple   apple ;
    Banana  banana ;

    sub( apple ) ;
    sub( banana ) ;

    return  0 ;
}

/* 実行結果
あー、おなかすいた。
リンゴを洗う
ナイフで6つに切る
ナイフで皮をむく
食べる「パクパク」
あー、おいしかった。

あー、おなかすいた。
バナナの皮をむく
食べる「ムシャムシャ」
あー、おいしかった。

Press any key to continue
*/

[生成] FactoryMethod パターン
インスタンスの生成は派生クラスに任せる。
FactoryMethod は TemplateMethod から呼ばれる簡単な生成パターン。
#include <stdio.h> // puts()

// FactoryMethod パターン

class ProductPtn // 抽象的な製品
{
public:
    virtual void  Name_Put() = 0 ; // 製品の共通機能
} ;

class FactoryMethodPtn // 工場パターン
{
    // 製品のインスタンス生成を分離するところが FactoryMethod の特徴?
    virtual ProductPtn *  FactoryMethod() = 0 ;  // <- 未実装

public:
    void  TemplateMethod() // 工場の製品紹介(骨組み)
    {
        printf( "今年は「" ) ;
        {
            ProductPtn *  product = FactoryMethod() ; // <- 未実装
            product->Name_Put() ;                     // 製品の共通機能 
            delete  product ;
        }
        printf( "」がおいしいですよ。\n" ) ;
    }
} ;

// 具体的な製品の実装

class Apple : public ProductPtn
{
public:
    virtual void  Name_Put() // 製品の共通機能 
    {
        printf( "リンゴ" ) ;
    }
} ;

class Banana : public ProductPtn
{
public:
    virtual void  Name_Put() // 製品の共通機能 
    {
        printf( "バナナ" ) ;
    }
} ;

// 具体的な工場の実装

class AppleFactory : public FactoryMethodPtn // リンゴ工場
{
public:
    virtual ProductPtn *  FactoryMethod() // 製品のインスタンス生成
    {
        // 個人的には new して返すのは嫌いなんだけど。
        return  new Apple() ;
    }
} ;

class BananaFactory : public FactoryMethodPtn // バナナ工場
{
public:
    virtual ProductPtn *  FactoryMethod() // 製品のインスタンス生成
    {
        // 個人的には new して返すのは嫌いなんだけど。
        return  new Banana() ;
    }
} ;

int main()
{
    AppleFactory   apple_factory ;    // リンゴ工場
    BananaFactory  banana_factory ;   // バナナ工場

    apple_factory.TemplateMethod() ;  // 工場の製品紹介
    banana_factory.TemplateMethod() ; // 工場の製品紹介

    return 0 ;
}

/* 実行結果
今年は「リンゴ」がおいしいですよ。
今年は「バナナ」がおいしいですよ。
Press any key to continue
*/

[生成] FactoryMethod パターン (非継承版)
インスタンスの生成は派生クラスに任せる。
FactoryMethod は TemplateMethod から呼ばれる簡単な生成パターン。
#include <stdio.h> // puts()

templateclass _ProductPtn >
class FactoryMethodPtn // 工場パターン
{
public:
    void  TemplateMethod() // 工場の製品紹介(骨組み)
    {
        printf( "今年は「" ) ;
        {
            _ProductPtn  product ; // <- 未実装
            product.Name_Put() ;   // 製品の共通機能 
        }
        printf( "」がおいしいです。\n" ) ;
    }
} ;

// 具体的な製品の実装

class Apple
{
public:
    void  Name_Put() // 製品の共通機能 
    {
        printf( "リンゴ" ) ;
    }
} ;

class Banana
{
public:
    void  Name_Put() // 製品の共通機能 
    {
        printf( "バナナ" ) ;
    }
} ;

int main()
{
    FactoryMethodPtn< Apple >   apple_factory ;  // リンゴ工場
    FactoryMethodPtn< Banana >  banana_factory ; // バナナ工場

    apple_factory.TemplateMethod() ;  // 工場の製品紹介
    banana_factory.TemplateMethod() ; // 工場の製品紹介

    return 0 ;
}

/* 実行結果
今年は「リンゴ」がおいしいです。
今年は「バナナ」がおいしいです。
ress any key to continue
*/

[生成] Prototype パターン
クローンを作る。「クローンパターン」と言ったほうがわかりやすいのにね。
あらかじめ試作品を作っておいて、必要な時にコピー(複製)するパターン。
#include <stdio.h> // printf()

// Prototype パターン

class PrototypePtn // クローンメソッドがPrototypeの特徴?
{
public:
    virtual PrototypePtn *  Clone() = 0 ; // クローンメソッド

    // 共通機能?(もっと複雑な設定値があると思われ)
    char                    m_value ; // 値
} ;

// 具体的な実装

class Apple : public PrototypePtn
{
public:
    Apple()
    {
        m_value = 'a' ;
    }

    virtual PrototypePtn *  Clone() // クローン
    {
        Apple *  prototype = new Apple ;

        prototype->m_value = m_value ; // 値

        return  prototype ;
    }
} ;

class Banana : public PrototypePtn
{
public:
    Banana()
    {
        m_value = 'b' ;
    }

    virtual PrototypePtn *  Clone() // クローン
    {
        Banana *  prototype = new Banana ;

        prototype->m_value = m_value ; // 値

        return  prototype ;
    }
} ;

int main()
{
    Apple   apple ;
    Banana  banana ;

    #define MAX  8
    PrototypePtn *  box[MAX][MAX] ; // 箱

    // 箱に並べる
    {
        for ( int y=0 ; y<MAX ; ++y )
        {
            for ( int x=0 ; x<MAX ; ++x )
            {
                box[y][x] = (x + y) % 3 ? apple.Clone() : banana.Clone() ;
            }
            // 途中から種類を変えてみたりして、^^;
            if ( y == 2 ) apple.m_value  = 'A' ;
            if ( y == 4 ) banana.m_value = 'B' ;
        }
    }
    // 箱の中身を表示
    {
        for ( int y=0 ; y<MAX ; ++y )
        {
            for ( int x=0 ; x<MAX ; ++x )
            {
                printf( " %c", box[y][x]->m_value ) ;
            }
            printf( "\n" ) ;
        }
    }
    // 破棄
    {
        for ( int y=0 ; y<MAX ; ++y )
        {
            for ( int x=0 ; x<MAX ; ++x )
            {
                delete box[y][x] ;
            }
        }
    }
    #undef MAX

    return  0 ;
}

/* 実行結果
 b a a b a a b a
 a a b a a b a a
 a b a a b a a b
 b A A b A A b A
 A A b A A b A A
 A B A A B A A B
 B A A B A A B A
 A A B A A B A A
Press any key to continue
*/

[生成] Prototype パターン (非継承版)
クローンを作る。「クローンパターン」と言ったほうがわかりやすいのにね。
あらかじめ試作品を作っておいて、必要な時にコピー(複製)するパターン。
#include <stdio.h> // printf()

// Prototype パターン

class PrototypePtn // クローンメソッド無しで実装してみたりして^^;
{
public:
    // 共通機能?(もっと複雑な設定値があると思われ)
    char  m_value ; // 値
} ;

// 具体的な実装

int main()
{
    PrototypePtn  apple ;  apple.m_value  = 'a' ;
    PrototypePtn  banana ; banana.m_value = 'b' ;

    #define MAX  8
    PrototypePtn  box[MAX][MAX] ; // 箱

    // 箱に並べる
    {
        for ( int y=0 ; y<MAX ; ++y )
        {
            for ( int x=0 ; x<MAX ; ++x )
            {
                // C++ なら普通にコピーしても問題無いよね。^^;
                box[y][x] = (x + y) % 3 ? apple : banana ;
            }
            // 途中から種類を変えてみたりして、^^;
            if ( y == 2 ) apple.m_value  = 'A' ;
            if ( y == 4 ) banana.m_value = 'B' ;
        }
    }
    // 箱の中身を表示
    {
        for ( int y=0 ; y<MAX ; ++y )
        {
            for ( int x=0 ; x<MAX ; ++x )
            {
                printf( " %c", box[y][x].m_value ) ;
            }
            printf( "\n" ) ;
        }
    }
    #undef MAX

    return  0 ;
}

/* 実行結果
 b a a b a a b a
 a a b a a b a a
 a b a a b a a b
 b A A b A A b A
 A A b A A b A A
 A B A A B A A B
 B A A B A A B A
 A A B A A B A A
Press any key to continue
*/

[生成] Singleton パターン
インスタンスを一つしか生成しないパターン。
場合によってはインスタンスの数を制限するのにも使う。
わりとよく使われているパターンだと思う。
#include <stdio.h> // puts()

// 既存のクラス

class Apple
{
    int  m_cnt ; // 総数

public:
    Apple() : m_cnt( 6 ) {}  // 総数6個

    void  Eat( int in )
    {
        if ( m_cnt >= in )
        {
            m_cnt -= in ;
            printf( "%d 個、食べました。残りは %d 個です。\n", in, m_cnt ) ;
        }
        else
        {
            printf( "%d 個ありません。残りは %d 個です。\n", in, m_cnt ) ;
        }
    }
} ;

// Singleton パターン

class SingletonPtn
{
    static Apple *  m_apple ; // インスタンスは一つ

    SingletonPtn() {} // <- このクラスのインスタンス化を抑止

public:
    static Apple* Instance_Get()
    {
        // Apple を1つしか作らないのが Singleton の特徴
        if ( m_apple == 0 )
        {
            m_apple = new Apple() ;
        }

        return  m_apple ;
    }

    static void  Instance_Delete()
    {
        if ( m_apple != 0 )
        {
            delete m_apple ;
            m_apple = 0 ;
        }
    }
} ;

Apple* SingletonPtn::m_apple = 0 ; // インスタンスは一つ

int main()
{
    Apple *  ryoko  = SingletonPtn::Instance_Get() ;
    Apple *  manami = SingletonPtn::Instance_Get() ;
    Apple *  ai     = SingletonPtn::Instance_Get() ;

    ryoko ->Eat( 1 ) ;
    manami->Eat( 2 ) ;
    ai    ->Eat( 1 ) ;
    ryoko ->Eat( 1 ) ;
    manami->Eat( 2 ) ;
    ai    ->Eat( 1 ) ;

    SingletonPtn::Instance_Delete() ;

    return  0 ;
}

/* 実行結果
1 個、食べました。残りは 5 個です。
2 個、食べました。残りは 3 個です。
1 個、食べました。残りは 2 個です。
1 個、食べました。残りは 1 個です。
2 個ありません。残りは 1 個です。
1 個、食べました。残りは 0 個です。
Press any key to continue
*/

[生成] Singleton パターン (非継承版)
インスタンスを一つしか生成しないパターン。
場合によってはインスタンスの数を制限するのにも使う。
わりとよく使われているパターンだと思う。
#include <stdio.h> // puts()

// 既存のクラス

class Apple
{
    int  m_cnt ; // 総数

public:
    Apple() : m_cnt( 6 ) {}  // 総数6個

    void  Eat( int in )
    {
        if ( m_cnt >= in )
        {
            m_cnt -= in ;
            printf( "%d 個、食べました。残りは %d 個です。\n", in, m_cnt ) ;
        }
        else
        {
            printf( "%d 個ありません。残りは %d 個です。\n", in, m_cnt ) ;
        }
    }
} ;

// Singleton パターン なんて使わなくても、
// リファレンスを使えばよいような気も。ダメ?^^;

int main()
{
    Apple    apple ; // インスタンスは1つ
    Apple &  ryoko  = apple ;
    Apple &  manami = apple ;
    Apple &  ai     = apple ;

    ryoko .Eat( 1 ) ;
    manami.Eat( 2 ) ;
    ai    .Eat( 1 ) ;
    ryoko .Eat( 1 ) ;
    manami.Eat( 2 ) ;
    ai    .Eat( 1 ) ;

    return  0 ;
}

/* 実行結果
1 個、食べました。残りは 5 個です。
2 個、食べました。残りは 3 個です。
1 個、食べました。残りは 2 個です。
1 個、食べました。残りは 1 個です。
2 個ありません。残りは 1 個です。
1 個、食べました。残りは 0 個です。
Press any key to continue
*/

last update 2003/03/28
since 2001/12/11