使用工厂模式按名称实例化类 [英] Instantiating classes by name with factory pattern

查看:97
本文介绍了使用工厂模式按名称实例化类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个类 A,B,C,... 的列表,它们都继承自 Base



我从用户那里得到一个字符串的类名,我想实例化正确的类,并返回一个指针 Base



我想到使用以类名作为键的散列表,以及指向实例化正确类的函数的函数指针返回 Base *



但是,我想我可以使用这里的工厂模式

解决方案

这是一个非常简单的方法,以下是一个通用的工厂示例实施:

 模板< class Interface,class KeyT = std :: string> 
struct Factory {
typedef KeyT Key;
typedef std :: auto_ptr< Interface>类型;
typedef类型(* Creator)();

bool define(Key const& key,Creator v){
//定义键 - > v关系,返回这是否是一个新的键。
return _registry.insert(typename Registry :: value_type(key,v))。
}
类型create(Key const& key){
typename Registry :: const_iterator i = _registry.find(key);
if(i == _registry.end()){
throw std :: invalid_argument(std :: string(__ PRETTY_FUNCTION__)+
:key not registered
}
else return i-> second();
}

template< class Base,class Actual>
static
std :: auto_ptr< Base> create_func(){
return std :: auto_ptr< Base>(new Actual());
}

private:
typedef std :: map< Key,Creator>注册表;
注册表_registry;
};

这并不意味着在任何情况下都是最好的,并且比手动实现所提到的类型的函数stijn更有用的默认。每个层次结构应注册自身的方式不是Factory强制要求的,但您可能喜欢方法 gf提到(这是简单,清楚,非常有用,是的,这克服了宏的固有问题在这种情况下)。



这是工厂的简单示例

  struct Base {
typedef :: Factory<厂;
virtual〜Base(){}
virtual int answer()const = 0;

static Factory :: Type create(Factory :: Key const& name){
return _factory.create(name);
}
template< class Derived>
static void define(Factory :: Key const& name){
bool new_key = _factory.define(name,
& Factory :: template create_func< Base,Derived>);
if(not new_key){
throw std :: logic_error(std :: string(__ PRETTY_FUNCTION__)+
:name already registered);
}
}

private:
static Factory _factory;
};
Base :: Factory Base :: _ factory;

struct A:Base {
virtual int answer()const {return 42; }
};

int main(){
Base :: define< A>(A);
assert(Base :: create(A) - > answer()== 42);
return 0;
}


Suppose I have a list of classes A, B, C, ... which all inherit from Base.

I get the class name as a string from the user, and I want to instantiate the right class and return a pointer to Base. How would you implement this?

I thought of using a hash-table with the class name as the key, and a function pointer to a function that instantiates the right class and returns a Base *.

However, I think I might be able to use the factory pattern here and make it a lot easier, but I just can't quite remember it well, so I though I'd ask for suggestions.

解决方案

Here is a generic factory example implementation:

template<class Interface, class KeyT=std::string>
struct Factory {
    typedef KeyT Key;
    typedef std::auto_ptr<Interface> Type;
    typedef Type (*Creator)();

    bool define(Key const& key, Creator v) {
        // Define key -> v relationship, return whether this is a new key.
        return _registry.insert(typename Registry::value_type(key, v)).second;
    }
    Type create(Key const& key) {
        typename Registry::const_iterator i = _registry.find(key);
        if (i == _registry.end()) {
            throw std::invalid_argument(std::string(__PRETTY_FUNCTION__) +
                                        ": key not registered");
        }
        else return i->second();
    }

    template<class Base, class Actual>
    static
    std::auto_ptr<Base> create_func() {
        return std::auto_ptr<Base>(new Actual());
    }

private:
    typedef std::map<Key, Creator> Registry;
    Registry _registry;
};

This is not meant to be the best in every circumstance, but it is intended to be a first approximation and a more useful default than manually implementing the type of function stijn mentioned. How each hierarchy should register itself isn't mandated by Factory, but you may like the method gf mentioned (it's simple, clear, and very useful, and yes, this overcomes the inherent problems with macros in this case).

Here's a simple example of the factory:

struct Base {
    typedef ::Factory<Base> Factory;
    virtual ~Base() {}
    virtual int answer() const = 0;

    static Factory::Type create(Factory::Key const& name) {
        return _factory.create(name);
    }
    template<class Derived>
    static void define(Factory::Key const& name) {
        bool new_key = _factory.define(name,
            &Factory::template create_func<Base, Derived>);
        if (not new_key) {
            throw std::logic_error(std::string(__PRETTY_FUNCTION__) +
                                   ": name already registered");
        }
    }

private:
    static Factory _factory;
};
Base::Factory Base::_factory;

struct A : Base {
    virtual int answer() const { return 42; }
};

int main() {
    Base::define<A>("A");
    assert(Base::create("A")->answer() == 42);
    return 0;
}

这篇关于使用工厂模式按名称实例化类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆