C++ で、Model-View-Controller とか

結構適当。
MVC 自体うろ覚えなので、ところどころ間違っているかも。
あんまり Pluggable じゃない気もする。

[ソース]

#include <iostream>
#include <boost/signals2.hpp>

template<typename T>
struct hp_view1{
    void operator()(T const& model){
        view(model);
    }
    void view(T const& model){
        std::cout << model.hp() << "/" << model.max_hp() << std::endl;
    }
};

template<typename T>
struct hp_view2{
    void operator()(T const& model){
        view(model);
    }
    void view(T const& model) const{
        for(int i = 0 ; i < model.hp() ; ++i){
            std::cout << "*";
        }
        std::cout << "\n";
    }
};

template<typename T, typename U>
struct damage_view{
    damage_view(U& controller) : controller_(controller){}
    void operator()(T const&){}
    void damage(int n){
        controller_.down(n);
    }
private:
    U& controller_;
};

template<typename T, typename U>
struct cure_view{
    cure_view(U& controller) : controller_(controller){}
    void operator()(T const&){}
    void cure(int n){
        controller_.up(n);
    }
private:
     U& controller_;
};

template<typename T>
struct hp_controller{
    hp_controller(T& model) : model_(model){}
    void up(int n){
        int hp = model_.hp() + n;
        model_.hp( (hp > model_.max_hp()) ? model_.max_hp() : hp);
    }
    void down(int n){
        int hp = model_.hp() - n;
        model_.hp((n < 0) ? 0 : hp);
    }
    T& model_;
};

struct character{
    static int const max_hp_ = 5;
    character() : hp_(max_hp_){}
    
    int hp() const{
        return hp_;
    }
    void hp(int hp){
        hp_ = hp;
        observer_(*this);
    }
    int max_hp() const{
        return max_hp_;
    }
    template<typename F>
    void add_observer(F f){
        observer_.connect(f);
    }
private:
    int hp_;
    boost::signals2::signal<void(character const&)> observer_;
};

int
main(){
    character model;
    
    hp_view1<character> view1;
    model.add_observer(view1);
    hp_view2<character> view2;
    model.add_observer(view2);
    
    hp_controller<character> hp(model);
    damage_view<character, hp_controller<character> > view3(hp);
    cure_view<character, hp_controller<character> >   view4(hp);
    
    view3.damage(1);
    view3.damage(1);
    view3.damage(1);
    view4.cure(3);

    return 0;
}

[出力]

4/5
****
3/5
***
2/5
**
5/5
*****

MVCアーキテクチャ自体は好きなんですけど、コードを書くと複雑になってしまうのでぐぬぬ……。
もうちょっとスマートにしたいですねぇ。

[boost]

  • ver 1.47.0