Factory Method II


Description:

Example:

Note

Idea:

User可以直接往engine factory里加入可用的engine,然后就不用修改engine factor的code了。非常炫酷。

注意定义的顺序,有些必须那样。

Code:

Method 1 engine factory里有很多static members。

#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;

class CalcEngine{
public:
    CalcEngine()=default;
    virtual ~CalcEngine()=default;
    virtual int run(const vector<int> &)=0;
};

class Multiplier: public CalcEngine{
public:
    Multiplier();

    int run(const vector<int> & nums) override{
        int result=0;
        for(auto e: nums){
            result += e;
        }
        return result;
    }
};


class EngineFactory{
public:
    static CalcEngine * newCalcEngine(const string& engine_name){
        if(engine_dict_.find(engine_name)==engine_dict_.end()) return nullptr;
        else return engine_dict_[engine_name];
    }
    static void setEngineDict(string engine_name, CalcEngine& engine_obj){
        cout<<"Set engine: "<<engine_name<<endl;
        engine_dict_[engine_name] = &engine_obj;
    }

    static void listEngines(){
        cout<<"Engine list:\n";
        for(auto e: engine_dict_){
            cout<<e.first<<endl;
        }
    }

private:
    EngineFactory(){}
    EngineFactory(const EngineFactory &);
    ~EngineFactory(){}
    static unordered_map<string, CalcEngine *> engine_dict_;
};

// Initialize static variable hash_map as empty
unordered_map<string, CalcEngine *> EngineFactory::engine_dict_;

// 这个顺序! after class Multiplier and EngineFactory
Multiplier multiplier_obj;
Multiplier::Multiplier(){
    EngineFactory::setEngineDict("multiplier", multiplier_obj);
}


int main(){
    string engine_name="multiplier";

    vector<int> nums={1, 2, 3, 4};

    CalcEngine * engine_ptr = EngineFactory::newCalcEngine(engine_name);
    if(engine_ptr!=nullptr)
        cout<<engine_ptr->run(nums)<<endl;

    EngineFactory::listEngines();
}

Method 2 engine factory用singleton design。避免用很多的static members。

#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;

class CalcEngine{
public:
    CalcEngine()=default;
    virtual ~CalcEngine()=default;
    virtual int run(const vector<int> &)=0;
};

class Multiplier: public CalcEngine{
public:
    Multiplier();

    int run(const vector<int> & nums) override{
        int result=0;
        for(auto e: nums){
            result += e;
        }
        return result;
    }
};


class EngineFactory{
public:
    CalcEngine * newCalcEngine(const string& engine_name){
        if(engine_dict_.find(engine_name)==engine_dict_.end()) return nullptr;
        else return engine_dict_[engine_name];
    }
    void setEngineDict(string engine_name, CalcEngine& engine_obj){
        cout<<"Set engine: "<<engine_name<<endl;
        engine_dict_[engine_name] = &engine_obj;
    }

    void listEngines(){
        cout<<"Engine list:\n";
        for(auto e: engine_dict_){
            cout<<e.first<<endl;
        }
    }

    static EngineFactory * getInstance(){
        if(instance_ptr_==nullptr){
            instance_ptr_=new EngineFactory();
        }
        return instance_ptr_;
    }

private:
    EngineFactory(){}
    EngineFactory(const EngineFactory &);
    ~EngineFactory(){}
    unordered_map<string, CalcEngine *> engine_dict_;
    static EngineFactory * instance_ptr_;
};

EngineFactory * EngineFactory::instance_ptr_=nullptr;

Multiplier multiplier_obj;
Multiplier::Multiplier(){
    EngineFactory::getInstance()->setEngineDict("multiplier", multiplier_obj);
}

int main(){
    string engine_name="multiplier";

    vector<int> nums={1, 2, 3, 4};

    CalcEngine * engine_ptr = EngineFactory::getInstance()->newCalcEngine(engine_name);
    if(engine_ptr!=nullptr)
        cout<<engine_ptr->run(nums)<<endl;

    EngineFactory::getInstance()->listEngines();
}

results matching ""

    No results matching ""