続・続・ interface と実装を分離する
長いんだけど http://d.hatena.ne.jp/janus_wel/20100608/1275989229 の最後で言ってた interface の管理用 class の実装例を書いてみた。長くなったついでに複数の似たような object を管理できるようにもしてみた。以下の code では id という整数値を指定して object への参照を得ているけど unique な値の集合であればなんでもいいので例えば file の絶対 path やら MD5 やらに応用が可能なはず。
// interface.hpp #ifndef INTERFACE_HPP #define INTERFACE_HPP #include <string> namespace sample { struct interface_type { virtual void print(void) const = 0; virtual void set(const std::string& str) = 0; }; struct controler_type { virtual interface_type& use(int id) = 0; virtual void release(const interface_type& target) = 0; }; // Returning reference controler_type& controler(void); } #endif // INTERFACE_HPP
// implement.cpp #include "interface.hpp" #include <algorithm> #include <functional> #include <iostream> #include <list> #include "../../../github/cpplib/header/algorithm.hpp" namespace sample { namespace implement { class concrete_type : public interface_type { private: const int mv_id; std::string mv_str; public: concrete_type(int id) : mv_id(id), mv_str("concrete") { std::cout << "concrete_type(" << mv_id << ")" << std::endl; } ~concrete_type(void) { std::cout << "~concrete_type(" << mv_id << ")" << std::endl; } void print(void) const { std::cout << mv_str << std::endl; } void set(const std::string& str) { mv_str = str; } const bool is_me(int id) const { return mv_id == id; } public: bool operator==(const concrete_type& rhs) { return mv_id == rhs.mv_id; } bool operator!=(const concrete_type& rhs) { return !(*this == rhs); } private: concrete_type& operator=(const concrete_type&); }; class ccontroler_type : public controler_type { private: typedef std::list<concrete_type*> concrete_array_type; private: concrete_array_type concrete_array; public: ~ccontroler_type(void) { std::for_each( concrete_array.rbegin(), concrete_array.rend(), util::algorithm::sweeper()); } interface_type& use(int id) { concrete_array_type::iterator found = std::find_if( concrete_array.begin(), concrete_array.end(), std::bind2nd(std::mem_fun( &sample::implement::concrete_type::is_me ), id)); // found if (found != concrete_array.end()) return **found; // not found and create concrete_type* created = new implement::concrete_type(id); concrete_array.push_back(created); return *created; } void release(const interface_type& target) { concrete_array_type::iterator found = std::find( concrete_array.begin(), concrete_array.end(), &target); if (found != concrete_array.end()) { delete *found; concrete_array.erase(found); } } }; } controler_type& controler(void) { static implement::ccontroler_type controler; return controler; } }
// main.cpp #include "interface.hpp" using namespace sample; int main(void) { interface_type& i01 = controler().use(1); i01.set("one"); i01.print(); interface_type& i02 = controler().use(2); i02.set("two"); i02.print(); controler().release(i01); interface_type& i03 = controler().use(3); i03.set("three"); i03.print(); interface_type& i04 = controler().use(2); i04.set("four"); i04.print(); return 0; }