Is dependency injection useful in C++

前端 未结 5 1464
暗喜
暗喜 2021-01-31 02:39

C# uses Dependency Injection (DI) a lot to have a lossless and testable platform. For this, I need

5条回答
  •  花落未央
    2021-01-31 03:28

    With C++11 as a project limit I ended up rolling my own. I loosely based it on .NET Ninject API without the Reflection ofcourse.

    ServiceLocator

    Note, although its called ServiceLocator (since it does not do Dependancy Injection itself) if you use lambda function bindings and preferably ServiceLocator::Module classes you get Injection (not reflection based) and it works really really well (IMO)

    #include 
    #include 
    #include "ServiceLocator.hpp"
    
    template 
    using sptr = std::shared_ptr;
    
    // Some plain interfaces
    class IFood {
    public:
        virtual std::string name() = 0;
    };
    
    class IAnimal {
    public:
        virtual void eatFavouriteFood() = 0;
    };
    
    
    // Concrete classes which implement our interfaces, these 2 have no dependancies
    class Banana : public IFood {
    public:
        std::string name() override {
            return "Banana";
        }
    };
    
    class Pizza : public IFood {
    public:
        std::string name() override {
            return "Pizza";
        }
    };
    
    // Monkey requires a favourite food, note it is not dependant on ServiceLocator
    class Monkey : public IAnimal {
    private:
        sptr _food;
    
    public:
        Monkey(sptr food) : _food(food) {
        }
    
        void eatFavouriteFood() override {
            std::cout << "Monkey eats " << _food->name() << "\n";
        }
    };
    
    // Human requires a favourite food, note it is not dependant on ServiceLocator
    class Human : public IAnimal {
    private:
        sptr _food;
    
    public:
        Human(sptr food) : _food(food) {
        }
    
        void eatFavouriteFood() override {
            std::cout << "Human eats " << _food->name() << "\n";
        }
    };
    
    /* The SLModule classes are ServiceLocator aware, and they are also intimate with the concrete classes they bind to
       and so know what dependancies are required to create instances */
    class FoodSLModule : public ServiceLocator::Module {
    public:
        void load() override {
            bind("Monkey").to([] (SLContext_sptr slc) { 
                return new Banana();
            });
            bind("Human").to([] (SLContext_sptr slc) { 
                return new Pizza();
            });
        }
    };
    
    class AnimalsSLModule : public ServiceLocator::Module {
    public:
        void load() override {
            bind("Human").to([] (SLContext_sptr slc) { 
                return new Human(slc->resolve("Human"));
            });
            bind("Monkey").to([] (SLContext_sptr slc) { 
                return new Monkey(slc->resolve("Monkey"));
            });
        }
    };
    
    int main(int argc, const char * argv[]) {
        auto sl = ServiceLocator::create();
    
        sl->modules()
            .add()
            .add();
    
        auto slc = sl->getContext();
    
        std::vector> animals;
        slc->resolveAll(&animals);
    
        for(auto animal : animals) {
            animal->eatFavouriteFood();
        }
    
        return 0;
    }
    

提交回复
热议问题