Modern c++ design 第8章

来源:互联网 发布:mac唱歌软件 编辑:程序博客网 时间:2024/05/17 07:47

    Object Factories.

抽象工厂, 基于多态的实现, 面向接口的设计, 为了避免在实现中对具体的派生类的引用。通常使用Object Factories来生成具体对象。

通常的最简单实现方法是, 给Factory传入一个identifyId, 根据id, factory生成一个具体的对象, 返回基类接口。 但是这样的做法, 工厂还是对具体类有依赖, 而且每次加一个新的对象, 都要修改数个文件, 有较强的耦合性。

 用来处理这个问题的办法是: 让工厂维护一个由函数指针构成的集合, 不同的指针生成不同的对象, 需要加入对象的类,只需要在工厂注册自己的id和方法即可。

有了解决方案, 接下来就是泛化这个解决方案了, 思路完全相同, 只是加了几个template参数。 实现如下:

  template
    <
        class AbstractProduct,
        typename IdentifierType,
        typename ProductCreator = AbstractProduct* (*)(),
        template<typename, class>
            class FactoryErrorPolicy = DefaultFactoryError
    >
    class Factory
        : public FactoryErrorPolicy<IdentifierType, AbstractProduct>
    {
    public:
        bool Register(const IdentifierType& id, ProductCreator creator)
        {
            return associations_.insert(
                typename IdToProductMap::value_type(id, creator)).second;
        }
       
        bool Unregister(const IdentifierType& id)
        {
            return associations_.erase(id) == 1;
        }
       
        AbstractProduct* CreateObject(const IdentifierType& id)
        {
            typename IdToProductMap::iterator i = associations_.find(id);
            if (i != associations_.end())
            {
                return (i->second)();
            }
            return this->OnUnknownType(id);
        }
       
    private:
        typedef AssocVector<IdentifierType, ProductCreator> IdToProductMap;
        IdToProductMap associations_;
    };

最后还介绍了一个CloneFactory, 和ObjectFactory很类似, 区别在于CloneFactory依赖typeInfo来找寻Clone函数, 同时函数指针的类型也不同,需要传入一个AbstractProduct对象。 其他基本雷同。如下:

   template
    <
        class AbstractProduct,
        class ProductCreator =
            AbstractProduct* (*)(const AbstractProduct*),
        template<typename, class>
            class FactoryErrorPolicy = DefaultFactoryError
    >
    class CloneFactory
        : public FactoryErrorPolicy<TypeInfo, AbstractProduct>
    {
    public:
        bool Register(const TypeInfo& ti, ProductCreator creator)
        {
            return associations_.insert(
                typename IdToProductMap::value_type(ti, creator)).second;
        }
       
        bool Unregister(const TypeInfo& id)
        {
            return associations_.erase(id) == 1;
        }
       
        AbstractProduct* CreateObject(const AbstractProduct* model)
        {
            if (model == 0) return 0;
           
            typename IdToProductMap::iterator i =
                associations_.find(typeid(*model));
            if (i != associations_.end())
            {
                return (i->second)(model);
            }
            return this->OnUnknownType(typeid(*model));
        }
       
    private:
        typedef AssocVector<TypeInfo, ProductCreator> IdToProductMap;
        IdToProductMap associations_;
    };

当然, Factory一般都是Singleton对象, 可以用前几章介绍的SingletonHolder包装, 一切ok. 省了大量代码, 耦合性也小。

这章重点在于ObjectFactory的概念, 以及如何分离ObjectFactory的需求, 以便将其泛化, 泛化的过程自然解耦。 至于泛化的实现, 相比于泛化的过程, 到显得简单了许多。

原创粉丝点击