<< 前 ホーム 次 >>

bakaid: 200612202

#ifndef DIContainer_hpp_guard
#define DIContainer_hpp_guard

#include <iostream>
#include <map>
#include <stdexcept>
#include <string>
#include <vector>

using namespace std;

class Prototype {
public:
    virtual ~Prototype() {}

    virtual Prototype* newInstance(map<string, Prototype*>& args) = 0;

    virtual ostream& display(ostream& os, int nspace) {
        string spaces(nspace, ' ');
        os << spaces << "Prototype";
        return os;
    }
};

class Dependency {
private:
    Prototype* prototype;
    vector<string> dependencies;

public:
    Dependency() : prototype(0) {}

    Dependency(Prototype* prototype, vector<string>& dependencies) :
        prototype(prototype), dependencies(dependencies) {}

    virtual ~Dependency() {}

    virtual vector<string> getDependencies() { return dependencies; }

    virtual Prototype* newComponent(map<string, Prototype*>& args) {
        return prototype->newInstance(args);
    }

    virtual void deletePrototype() { if (prototype) delete prototype; }
};

class DIContainer {
private:
    map<string, Dependency> services;
    map<string, Prototype*> instances;

public:
    virtual ~DIContainer() {
        deleteServices();
        deleteInstances();
    }

    virtual void regist(string name, Prototype* prototype,
                        vector<string>& dependency) {
        if (services.count(name) > 0) throw runtime_error("double register");
        Dependency dep(prototype, dependency);
        services.insert(make_pair(name, dep));
    }

    virtual Prototype* getInstance(string name) {
        if (instances.count(name) > 0) return instances[name];
        Dependency dep = services[name];
        vector<string> names = dep.getDependencies();
        map<string, Prototype*> args;
        for (vector<string>::iterator it = names.begin();
             it != names.end(); ++it) {
            Prototype* comp = getInstance(*it);
            args.insert(make_pair(*it, comp));
        }
        Prototype* result = dep.newComponent(args);
        instances.insert(make_pair(name, result));
        return result;
    }

private:
    virtual void deleteServices() {
        for (map<string, Dependency>::iterator it = services.begin();
             it != services.end(); ++it) {
            it->second.deletePrototype();
        }
    }

    virtual void deleteInstances() {
        for (map<string, Prototype*>::iterator it = instances.begin();
             it != instances.end(); ++it) {
            delete it->second;
        }
    }
};

#endif //  DIContainer_hpp_guard

#include "DIContainer.hpp"

class Cc : public Prototype {
public:
    Cc() {}
    Cc(map<string, Prototype*>& args) {}

    virtual ~Cc() {}

    virtual Prototype* newInstance(map<string, Prototype*>& args) {
        return new Cc(args);
    }

    virtual ostream& display(ostream& os, int nspace) {
        string spaces(nspace, ' ');
        os << spaces << "Cc" << endl;
        return os;
    }
};

class Bb : public Prototype {
private:
    Cc* c;

public:
    Bb() : c(0) {}
    Bb(map<string, Prototype*>& args) : c(0) {
        if (args.count("Cc") > 0) c = reinterpret_cast<Cc*>(args["Cc"]);
    }

    virtual ~Bb() {}

    virtual Prototype* newInstance(map<string, Prototype*>& args) {
        return new Bb(args);
    }

    virtual ostream& display(ostream& os, int nspace) {
        string spaces(nspace, ' ');
        os << spaces << "Bb" << endl;
        if (c) c->display(os, nspace + 2);
        return os;
    }
};

class Aa : public Prototype {
private:
    Bb* b;
    Cc* c;

public:
    Aa() : b(0), c(0) {}
    Aa(map<string, Prototype*>& args) : b(0), c(0) {
        if (args.count("Bb") > 0) b = reinterpret_cast<Bb*>(args["Bb"]);
        if (args.count("Cc") > 0) c = reinterpret_cast<Cc*>(args["Cc"]);
    }

    virtual ~Aa() {}

    virtual Prototype* newInstance(map<string, Prototype*>& args) {
        return new Aa(args);
    }

    virtual ostream& display(ostream& os, int nspace) {
        string spaces(nspace, ' ');
        os << spaces << "Aa" << endl;
        if (b) b->display(os, nspace + 2);
        if (c) c->display(os, nspace + 2);
        return os;
    }
};

int
main()
{
    DIContainer container;

    vector<string> aDep;
    aDep.push_back("Bb");
    aDep.push_back("Cc");
    container.regist("Aa", new Aa(), aDep);

    vector<string> bDep;
    bDep.push_back("Cc");
    container.regist("Bb", new Bb(), bDep);

    vector<string> cDep;
    container.regist("Cc", new Cc(), cDep);

    Prototype* compo = container.getInstance("Aa");
    compo->display(cout, 0);
    return 0;
}

本家Permlink

<< 前 ホーム 次 >>


Copyright © 1905 tko at jitu.org

バカが征く on Rails