• 使用C++实现设计模式(连载): 第二回 Factory 工厂模式


    本来打算原创的,但是读到的这篇文章非常好的诠释了我比较常用的工厂模式,因此这一回翻译一篇来自Cale Dunlap的一篇文章,这里先谢谢Cale。

    原文链接:

    http://www.codeproject.com/Articles/363338/Factory-Pattern-in-Cplusplus


    Definition 

    Basically a Factory consists of an interface class which is common to all of the implementation classes that the factory will create. Then you have the factory class which is usually a singleton class that spawns instances of these implementation classes.

    译文:

    定义

    一个典型的Factory 模式中一般包含一个接口类,所有的由工厂创造的实现类都继承自这个接口类。工厂类一般采用单例模式实现,由工厂类对象实例产生具体的实现类。

    Abstract Interface Class

    So let us create a quick interface class to start with. In this example, I used IAnimal

    译文:

    快让我们来创建一个接口类来开始我们的工厂模式之旅吧。在这个例子中,我们使用 IAnimal 来定义表示抽象动物的接口类。

    class IAnimal
    {
    public:
        virtual int GetNumberOfLegs() const = 0;
        virtual void Speak() = 0;
        virtual void Free() = 0;
    }; 

    Now for simplicity’s sake, I used a typedef to define a type for the function that is used by the implementation classes to create instances of IAnimal. This typedef is also used in declaring the map that maps the animal name to the function that creates that particular type of animal. You can use whatever calling convention you like, but for this example, I chose __stdcall.

    译文:

    为了代码的简洁,我使用typedef 来定义一个函数指针,用于方便在工厂类中创建继承自IAnimal 类的子类对象实例。这个typedef 定义同样用在根据动物名称来影射创建具体动物对象的函数中。你可以根据你的使用习惯来定义它,但是我习惯上选择__stdcall来声明函数。

    typedef IAnimal* (__stdcall *CreateAnimalFn)(void); 

    Specific Implementation Class(es) 

    Now come the implementation classes. These are the classes that implement the IAnimal interface. Here’re a few examples:

    译文:

    接着我们来定义具体实现的动物子类。这些类都实现了IAnimal 接口类。下面我们来看看几个例子:

    // IAnimal implementations
    class Cat : public IAnimal
    {
    public:
        int GetNumberOfLegs() const { return 4; }
        void Speak() { cout << “Meow” << endl; }
        void Free() { delete this; }
    
        static IAnimal * __stdcall Create() { return new Cat(); }
    };
    
    class Dog : public IAnimal
    {
    public:
        int GetNumberOfLegs() const { return 4; }
        void Speak() { cout << “Woof” << endl; }
        void Free() { delete this; }
    
        static IAnimal * __stdcall Create() { return new Dog(); }
    };
    
    class Spider : public IAnimal // Yeah it isn’t really an animal…
    {
    public:
        int GetNumberOfLegs() const { return 8; }
        void Speak() { cout << endl; }
        void Free() { delete this; }
    
        static IAnimal * __stdcall Create() { return new Spider(); }
    };
    
    class Horse : public IAnimal
    {
    public:
        int GetNumberOfLegs() const { return 4; }
        void Speak() { cout << “A horse is a horse, of course, of course.” << endl; }
        void Free() { delete this; }
    
        static IAnimal * __stdcall Create() { return new Horse(); }
    };

    Factory Class Declaration 

    Now comes the Factory class. This is a singleton pattern implementation--meaning only one instance of the factory can ever be instantiated, no more, no less.

    译文:

    下面我们来定义工厂类。我们采用单例模式来实现,这意味着能且只有一个工厂类实例被创建。

    // Factory for creating instances of IAnimal
    class AnimalFactory
    {
    private:
        AnimalFactory();
        AnimalFactory(const AnimalFactory &) { }
        AnimalFactory &operator=(const AnimalFactory &) { return *this; }
    
        typedef map FactoryMap;
        FactoryMap m_FactoryMap;
    public:
        ~AnimalFactory() { m_FactoryMap.clear(); }
    
        static AnimalFactory *Get()
        {
            static AnimalFactory instance;
            return &instance;
        }
    
        void Register(const string &animalName, CreateAnimalFn pfnCreate);
        IAnimal *CreateAnimal(const string &animalName);
    };

    Factory Class Implementation

    Now we need to work out a few definitions of the AnimalFactory class. Specifically the constructor, the Register, and the CreateAnimal functions.

    译文:

    现在我们来看看工厂类AnimalFactory 的成员函数定义。这里只分析默认构造函数,Register函数和 CreateAnimal 函数。

    Constructor

    The constructor is where you might consider registering your Factory functions. Though this doesn’t have to be done here, I’ve done it here for the purposes of this example. You could for instance register your Factory types with the Factory class from somewhere else in the code.

    译文:

    构造函数

    构造函数中需要注册工厂类中的注册工厂函数(可以生成的动物种类)。虽然这些函数不是在这里完成,但是必须在工厂类的构造函数中注册。当然你也可以工厂类的其他函数中注册该工厂可以支持的类型对象实例化函数。

    /* Animal factory constructor.
    Register the types of animals here.
    */
    AnimalFactory::AnimalFactory()
    {
        Register(“Horse”, &Horse::Create);
        Register(“Cat”, &Cat::Create);
        Register(“Dog”, &Dog::Create);
        Register(“Spider”, &Spider::Create);
    }

    Type Registration

    Now let us implement the Register function. This function is pretty straightforward since I used a std::map to hold the mapping between my string (the animal type) and the create function.

    译文:

    类型注册

    现在我们来实现注册成员函数。这个成员函数目标非常单一,我使用 std::map来影射动物类型名称和创建这个类型动物所需要的create 函数指针。

    void AnimalFactory::Register(const string &animalName, CreateAnimalFn pfnCreate)
    {
        m_FactoryMap[animalName] = pfnCreate;
    }

    Type Creation

    And last but not least, the CreateAnimal function. This function accepts a string parameter which corresponds to the string registered in the AnimalFactory constructor. When this function receives “Horse” for example, it will return an instance of the Horse class, which implements the IAnimal interface.

    译文:

    类型创建

    这里最后介绍CreateAnimal 函数(其他函数这里不做讲解),这个函数接受的第一个参数:字符串类型,代表在AnimalFactory 构造函数中注册了的可生成类型的名称(动物名称)。当这个函数收到参数“Horse”,工厂将要创建一个Horse类对象实例,这个类实现了IAnimal 接口。

    IAnimal *AnimalFactory::CreateAnimal(const string &animalName)
    {
        FactoryMap::iterator it = m_FactoryMap.find(animalName);
        if( it != m_FactoryMap.end() )
        return it->second();
        return NULL;
    }

    Example Usage Program

    最后,我们来看看工厂类的使用例子吧。

    int main( int argc, char **argv )
    {
        IAnimal *pAnimal = NULL;
        string animalName;
    
        while( pAnimal == NULL )
        {
            cout << “Type the name of an animal or ‘q’ to quit: “;
            cin >> animalName;
    
            if( animalName == “q” )
            break;
    
            IAnimal *pAnimal = AnimalFactory::Get()->CreateAnimal(animalName);
            if( pAnimal )
            {
                cout << “Your animal has ” << pAnimal->GetNumberOfLegs() << ” legs.” << endl;
                cout << “Your animal says: “;
                pAnimal->Speak();
            }
            else
            {
                cout << “That animal doesn’t exist in the farm! Choose another!” << endl;
            }
            if( pAnimal )
                pAnimal->Free();
            pAnimal = NULL;
            animalName.clear();
        }
        return 0;
    }

    注释:

    本来打算每周写一篇设计模式的文章的,五一放假期间偷懒没有写,以后要多多坚持。考虑到模式识别文章讲清楚比较难,以后两周写一次模式识别的文章吧。


  • 相关阅读:
    RecSys Challenge 2015
    Python 多行注释
    编译型语言与解释型语言
    vs2012 提示 未能正确加载 "Visual C++ Language Manager Package" 包
    人工智能 VS 机器学习 VS 深度学习
    CV-视频分析:静态背景下的运动检测
    消费者做出购买决策的流程
    Fat jar用途
    Eclipse中打包插件Fat Jar的安装与使用
    Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3057269.html
Copyright © 2020-2023  润新知