C++11 的工厂方法

参考:https://www.cnblogs.com/qicosmos/p/5090159.html

利用function和map构造一个简单工厂,生产的具体类需要继承自工厂生产的基类。利用模板类稍作改进,扩展到工厂方法。

 

工厂看上去是这样的

template <typename Base>
class Factory
{
public:
    typedef std::string KEY;

    template <typename Base>
    using CONSTRUCT = std::function<Base*(void)>;

    template <typename Base>
    using MAP_KEY_GENERATOR = std::map<KEY, CONSTRUCT<Base>>;

protected:

    static Factory<Base>& Get()
    {
        static Factory<Base> factory;
        return factory;
    }

    static MAP_KEY_GENERATOR<Base> _mapFunc;

}

这里的键是创建对象时提供的唯一标识,可以是string,其实也可以是typeid(class)的哈希值等等。CONSTRUCT提供一个构造函数。Base指向工厂生产产品的基类。

原代码中提供的私有函数对象封装了默认和形参构造函数的注入,使用new是为了复用代码,返回智能指针构造的对象

    template<typename Inherit>
    struct Register_t
    {
        Register_t(const KEY& key)
        {
            Factory<Base>::Get()._mapFunc.emplace(key, [] {return new Inherit(); });
        }

        template<typename...Args>
        Register_t(const KEY& key, Args...args)
        {
            Factory<Base>::Get()._mapFunc.emplace(key, [=] {return new Inherit(args...); });
        }

    };

上述的形参构造中无法在创建对象时才进行赋值,增加一个成员函数提高扩展性

    void Register(const KEY key,const Factory<Base>::CONSTRUCT<Base>& constrct)
    {
        Factory<Base>::Get()._mapFunc.emplace(key, constrct);
    }

接下来是一组生产具体对象的接口

    static Base* produce(const KEY& key)
    {
        if (_mapFunc.find(key) == _mapFunc.end())
        {
            return nullptr;
        }

        return _mapFunc[key]();
    }

    static SPTR<Base> produce_share(const KEY& key)
    {
        return SPTR<Base>(produce(key));
    }

    static UPTR<Base> produce_unique(const KEY& key)
    {
        return UPTR<Base>(produce(key));
    }

借助c++11 提供的特性,不需要100行代码,一个高复用的工厂方法基本成形

 

使用起来像这样,定义一些基类和具体类

class IBase
{
public:
    virtual ~IBase() {};

    virtual void Foo() {};

private:

};

class IBase2
{
public:
    virtual ~IBase2() {}
    virtual void Foo2() {}
private:

};

class InheritClass:public IBase
{
public:

    InheritClass()
    {
        std::cout << "build 1\n";
    }
    ~InheritClass()
    {
        std::cout << "destory 1\n";
    }

    void Func1()
    {
        std::cout << "funcs\n";
    }

    void Foo()
    {
        std::cout << "fucking work\n";
    }

private:

};

class InheritBClass :public IBase
{
public:
    InheritBClass()
    {
        std::cout << "bulid2\n";

    }
    ~InheritBClass()
    {
        std::cout << "destory2\n";
    }
    void Foo()
    {
        std::cout << "func2\n";
    }
};

class InheritBase2 :public IBase2
{
public:
    InheritBase2()
    {
        std::cout << "build 3\n";
    }

    InheritBase2(int a)
    {
        std::cout << "build 3 a:" << a << "\n";
    }

    InheritBase2(const std::string& b)
    {
        std::cout << "build 3 b:" << b << "\n";
    }
    ~InheritBase2()
    {
        std::cout << "destory 3\n";
    }
    void Foo2()
    {
        std::cout << "base2:: foo2\n";
    }

};

InheritBase2* Gene()
{
    std::cout << "Gene!\n";
    return new InheritBase2();
}

然后测试一波。需要先创建工厂类,再向工厂注册生产品,调用produce_进行生产。

void TestFactory()
{
    Factory<IBase> baseFactory;

    Factory<IBase>::Register_t<InheritClass> reg("build");
    Factory<IBase>::Register_t<InheritBClass> reg2("build2");

    auto pa = baseFactory.produce_share("build");
    pa->Foo();

    std::cout << "typed id " << typeid(InheritBClass).hash_code()<<"\n";


    auto pb = baseFactory.produce_unique("build2");

    std::cout << "typed id2 " << typeid(*pb).hash_code()<<"\n";


    Factory<IBase2> base2Factory;
    
    Factory<IBase2>::Register_t<InheritBase2> reg3("build3");
    auto pc = base2Factory.produce("build3");
    
    int a = 1;
    std::string b = "23333";

    Factory<IBase2>::Register_t<InheritBase2> reg4("build4", b);
    auto pc2 = base2Factory.produce_share("build4");

    auto func = [] {return new IBase2(); };
    base2Factory.Register("test",std::bind(&Gene));

    auto pd = base2Factory.produce("test");
}

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值