<< 前 ホーム 次 >>

bakaid: 20071227

// depinject.hxx
#include <functional>
#include <map>
#include <string>
#include <vector>

namespace DI {
    class DIComponent;
    typedef std::vector<DIComponent*> Compos;
    typedef std::vector<std::string> Strings;

    class DIComponent {
    public:
        virtual DIComponent* newInstance() = 0;
        virtual void acceptComponents(Compos& components) = 0;
    };

    class Dependency {
    private:
        std::string componentName;
        DIComponent* componentPrototype;
        Strings dependentNames;

    public:
        Dependency(std::string componentName, DIComponent* componentPrototype,
                   const char* dependentNames[])
            : componentName(componentName),
              componentPrototype(componentPrototype) {
            for (int i = 0; dependentNames[i]; ++i)
                this->dependentNames.push_back(dependentNames[i]);
        }

        virtual ~Dependency() {}

        virtual void deleteComponentPrototype() {
            delete componentPrototype;
        }

        virtual std::string getComponentName() {
            return componentName;
        }

        virtual DIComponent* getComponentPrototype() {
            return componentPrototype;
        }

        virtual Strings getDependentNames() {
            return dependentNames;
        }
    };

    class DIContainer {
    private:
        typedef std::map<std::string, DIComponent*> S2compo;

        S2compo components;
        std::vector<Dependency> dependencies;

    public:
        DIContainer() {}

        virtual ~DIContainer() {
            deleteComponents();
            deleteDependencies();
        }

        virtual void registerComponent(std::string componentName,
                                       DIComponent* componentPrototype,
                                       const char* dependentNames[]) {
            Dependency dep(componentName, componentPrototype, dependentNames);
            dependencies.push_back(dep);
        }

        virtual void assembleComponents() {
            newComponents();
            introduceComponents();
        }

        virtual DIComponent* getComponent(std::string componentName) {
            if (components.count(componentName) == 0)
                return 0;
            return components[componentName];
        }

    private:
        virtual void deleteComponents() {
            for_each(components.begin(), components.end(),
                     std::bind1st(std::mem_fun(&DIContainer::deleteComponent),
                                  this));
        }

        virtual void deleteComponent(S2compo::value_type pair) {
            delete pair.second;
        }

        virtual void deleteDependencies() {
            for_each(dependencies.begin(), dependencies.end(),
                     std::bind1st(std::mem_fun(&DIContainer::deleteDependency),
                                  this));
        }

        virtual void deleteDependency(Dependency dep) {
            dep.deleteComponentPrototype();
        }

        virtual void newComponents() {
            for_each(dependencies.begin(), dependencies.end(),
                     std::bind1st(std::mem_fun(&DIContainer::insertComponent),
                                  this));
        }

        virtual void insertComponent(Dependency dependency) {
            std::string name = dependency.getComponentName();
            DIComponent* prototype = dependency.getComponentPrototype();
            DIComponent* instance = prototype->newInstance();
            components.insert(make_pair(name, instance));
        }

        virtual void introduceComponents() {
            for (std::vector<Dependency>::iterator it = dependencies.begin();
                 it != dependencies.end(); ++it) {
                DIComponent* compo = getComponent(*it);
                if (!compo)
                    continue;
                Compos compos;
                Strings dependentNames = it->getDependentNames();
                getServices(dependentNames, compos);
                compo->acceptComponents(compos);
            }
        }

        virtual DIComponent* getComponent(Dependency dependency) {
            std::string name = dependency.getComponentName();
            if (components.count(name) == 0)
                return 0;
            return components[name];
        }

        virtual void getServices(Strings& dependentNames,
                                 Compos& ret_services) {
            for (Strings::iterator it = dependentNames.begin();
                 it != dependentNames.end(); ++it) {
                if (components.count(*it) == 0)
                    continue;
                DIComponent* compo = components[*it];
                ret_services.push_back(compo);
            }
        }
    };
}

// cxx.cxx
#include "depinject.hxx"
#include <iostream>

using namespace DI;
using namespace std;

class Openfilename : public DIComponent {
public:
    Openfilename() {}

    virtual ~Openfilename() {}

    virtual DIComponent* newInstance() {
        return new Openfilename();
    }

    virtual void acceptComponents(Compos& components) {}

    virtual bool open(string& path) {
        path = "Openfilename";
        return true;
    }
};

class Filer : public DIComponent {
private:
    Openfilename* openfilename;

public:
    Filer() : openfilename(0) {}

    virtual ~Filer() {}

    virtual DIComponent* newInstance() {
        return new Filer();
    }

    virtual void acceptComponents(Compos& components) {
        for (Compos::iterator it = components.begin();
             it != components.end(); ++it) {
            if (!openfilename) {
                openfilename = dynamic_cast<Openfilename*>(*it);
                if (openfilename)
                    continue;
            }
        }
    }

    virtual bool open(string& path) {
        return openfilename->open(path);
    }
};

class AppModel : public DIComponent {
private:
    Filer* filer;

public:
    AppModel() : filer(0) {}

    virtual ~AppModel() {}

    virtual DIComponent* newInstance() {
        return new AppModel();
    }

    virtual void acceptComponents(Compos& components) {
        for (Compos::iterator it = components.begin();
             it != components.end(); ++it) {
            if (!filer) {
                filer = dynamic_cast<Filer*>(*it);
                if (filer)
                    continue;
            }
        }
    }

    virtual void open() {
        string path;
        if (filer->open(path))
            cout << path << endl;
        else
            cout << "open failed" << endl;
    }
};

class AppControl : public DIComponent {
private:
    AppModel* model;

public:
    AppControl() : model(0) {}

    virtual ~AppControl() {}

    virtual DIComponent* newInstance() {
        return new AppControl();
    }

    virtual void acceptComponents(Compos& components) {
        for (Compos::iterator it = components.begin();
             it != components.end(); ++it) {
            if (!model) {
                model = dynamic_cast<AppModel*>(*it);
                if (model)
                    continue;
            }
        }
    }

    virtual void dispatch(string event) {
        if (event == "open")
            model->open();
    }
};

static void
registerOpenfilename(DIContainer* container)
{
    const char* name = "Openfilename";
    DIComponent* prototype = new Openfilename();
    const char* dependents[] = {0};
    container->registerComponent(name, prototype, dependents);
}

static void
registerFiler(DIContainer* container)
{
    const char* name = "Filer";
    DIComponent* prototype = new Filer();
    const char* dependents[] = {"Openfilename", 0};
    container->registerComponent(name, prototype, dependents);
}

static void
registerAppModel(DIContainer* container)
{
    const char* name = "AppModel";
    DIComponent* prototype = new AppModel();
    const char* dependents[] = {"Filer", 0};
    container->registerComponent(name, prototype, dependents);
}

static void
registerAppControl(DIContainer* container)
{
    const char* name = "AppControl";
    DIComponent* prototype = new AppControl();
    const char* dependents[] = {"AppModel", 0};
    container->registerComponent(name, prototype, dependents);
}

int
main()
{
    DIContainer container;
    registerOpenfilename(&container);
    registerFiler(&container);
    registerAppModel(&container);
    registerAppControl(&container);
    container.assembleComponents();
    DIComponent* compo = container.getComponent("AppControl");
    AppControl* control = dynamic_cast<AppControl*>(compo);
    control->dispatch("open");
    return 0;
}

本家Permlink

<< 前 ホーム 次 >>


Copyright © 1905 tko at jitu.org

バカが征く on Rails