0

我正在尝试找出解决以下问题的方法(精简版的实际代码,对于明显的内存泄漏感到抱歉):

#include <iostream>

namespace A {
    struct Product {
        virtual void doSomething() const =0;
    };

    template<typename T>
    struct SpecialProduct : public Product {
        T t;
        SpecialProduct(T t) : t(t) {};
        virtual void doSomething() const { std::cout << "A: " << t << " does something\n"; }
    };

    struct Factory {
        template<typename T>
        Product* create(T t = T()) const { return new SpecialProduct<T>(t); }
    };
}
namespace B {
    struct Product {
        virtual void doSomething() const =0;
    };

    template<typename T>
    struct SpecialProduct : public Product {
        T t;
        SpecialProduct(T t) : t(t) {};
        virtual void doSomething() const { std::cout << "B: " << t << " does something\n"; }
    };

    struct Factory {
        template<typename T>
        Product* create(T t = T()) const { return new SpecialProduct<T>(t); }
    };
}


struct ProductType { };

template<typename T>
struct SpecialProductType : public ProductType {};

int main() {

    // I have a factory of a known type
    A::Factory f;

    // standard procedure
    A::Product* p = f.create<int>();
    p->doSomething();

    // I have a product type description from some source
    ProductType* t = /* some source */ 0;

    // How do i get a product instance of type t from f?
    // A::Product* p = f. ???
}

我有一个模块的多个实现,在这种情况下在不同的命名空间中。工厂模式用于处理变体。每个模块都提供(抽象)产品和专门的通用版本。产品类型使用遵循相同模式的统一类基础结构表示。

我的问题是:给定一个指向专用产品类型的指针,我如何实现一个函数,从给定的工厂对象生成相应专用产品的实例?

非常感谢您的任何建议。

4

1 回答 1

0

经过几天的努力,我想出了以下解决方案:

#include <iostream>
#include <functional>
#include <typeinfo>
#include <typeindex>
#include <map>
#include <string>

using namespace std;

struct ProductType {
    type_index type;
    ProductType(type_index type) : type(type) {}
};

template<typename T>
struct SpecialProductType : public ProductType {
    SpecialProductType() : ProductType(typeid(T)) {}
};


template<typename Derived, typename _product_type>
struct FactoryBase {

    typedef _product_type product_type;

    map<type_index, function<product_type*()>> creators;

    template<typename T>
    void addProductType() {
        creators[typeid(T)] = [&]()->product_type* { 
            static_cast<Derived*>(this)->template create<T>(); 
        };
    }

    product_type* createForType(const ProductType& type) {
        return creators[type.type]();
    }
};  


namespace A {
    struct Product {
        virtual void doSomething() const =0;
    };

    template<typename T>
    struct SpecialProduct : public Product {
        T t;
        SpecialProduct(T t = T()) : t(t) {};
        virtual void doSomething() const { std::cout << "A: " << typeid(T).name() << " does something\n"; }
    };

    struct Factory : public FactoryBase<Factory,Product> {
        typedef Product product_type;
        template<typename T>
        Product* create() const { 
            std::cout << "A is creating a product of type " << typeid(T).name() << "\n";
                return new SpecialProduct<T>(); 
        }
    };
}
namespace B {
    struct Product {
        virtual void doSomething() const =0;
    };

    template<typename T>
    struct SpecialProduct : public Product {
        T t;
        SpecialProduct(T t = T()) : t(t) {};
        virtual void doSomething() const { std::cout << "B: " << typeid(T).name() << " does something\n"; }
    };

    struct Factory : public FactoryBase<Factory,Product> {
        typedef Product product_type;
        template<typename T>
        Product* create() const { 
            std::cout << "B is creating a product of type " << typeid(T).name() << "\n";
            return new SpecialProduct<T>(); 
        }
    };
}


int main() {

    // I have a factory of a known type
    A::Factory f;
    f.addProductType<float>();
    f.addProductType<string>();

    ProductType* tf = new SpecialProductType<float>();
    ProductType* ts = new SpecialProductType<string>();

    f.createForType(*tf)->doSomething();
    f.createForType(*ts)->doSomething();
}

本质上,我正在根据要在 FactoryBase 类中创建的产品类型构建自己的动态调度程序表。关键是泛型类型,值是能够创建适当实例的函子。

所提出的解决方案的缺点是需要注册支持类型的列表 - 但这可以在不更改工厂代码或产品类型的情况下完成(打开/关闭原则)。任何用户代码都可以动态扩展支持的产品类型列表。

于 2013-11-05T16:07:18.577 回答