[设计模式]两种方法实现简单工厂模式

<!--完整代码下载链接:点击下载完整代码示例-->

1.描述

在项目开发中经常会遇到根据不同的条件创建不同的对象,然后对该对象进行操作,一般都包括许多的switch -case分支如下:

CBase* pBase(NULL);
switch (type_variable)
{
    case obj1: pBase = new CBaseDerivate1();break;
    case obj2: pBase = new CBaseDerivate2();break;

    ...

    case objN: pBase = new CBaseDerivateN();break;
}

或者形如下面的情况:

CBase* pBase(NULL);

if (!strcmp(string_for_type, "Type1")) pBase = new CBaseDerivate1();
else if (!strcmp(string_for_type, "Type2")) pBase = new CBaseDerivate2();
    ...
else if (!strcmp(string_for_type, "TypeN")) pBase = new CBaseDerivateN();

上面两中创建对象的方法使用起来很繁琐,并且当对象的数量增加时,维护起来很麻烦,下面介绍简单工厂模式来解决该问,采用两种方法实现,一种是采用注册函数指针,另外一种采用模板参数。

2.两种方法实现简单工厂模式

例子:假设有一个动物类,需要根据不同的条件创建不同的动物

方法一:采用注册函数指针的方式

1.定义抽象动物类

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

2.定义具体的动物实例

// 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(); }
};

3.定义工厂

定义创建对象函数指针:

typedef IAnimal* (__stdcall *CreateAnimalFn)(void); 
// 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);
};

构造函数进行具体创建函数的注册

/* 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);
}

注册函数:

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

创建实例接口:

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

客户端使用方法:

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;
}

方法二:采用模板参数的方式

方法一需要每个子类都写一个创建实例的函数create,存在大量重复,同时,各个实例需要继承同一个父类,同时该方法比较容易理解。

下面采用模板参数的方法。

1.首先定义如下两个模板类

template <class BT>
class FactoryPlant
   {
   public:
      FactoryPlant() {}
      virtual ~FactoryPlant() {}
      virtual BT *createInstance() = 0;
   };

template <class BT,class ST>
class Factory : public FactoryPlant<BT>
   {
   public:
      Factory() {}
      virtual ~Factory() {}
      virtual BT *createInstance() {return new ST;}
   };

FactoryPlant为实际工厂类,Factory类有两个参数,一个是抽象基类BT,另一个是待实例化的类ST。 FactoryPlant
包含创建实例的纯虚函数createInstance,子类Factory实现该方法。

2.创建具体子类

 //抽象动物接口

class IAnimal
{
public:
	virtual int GetNumberOfLegs() const = 0;
	virtual void Speak() = 0;
	virtual void Free() = 0;
	typedef FactoryPlant<IAnimal> SimpleBaseClassFactory;
};
class Cat : public IAnimal
{
public:
	int GetNumberOfLegs() const { return 4; }
	void Speak() { cout << "Meow" << endl; }
	void Free() { delete this; }
    static Factory<IAnimal,Cat> myFactory;
};
Factory<IAnimal,Cat> Cat::myFactory;

class Dog : public IAnimal
{
public:
	int GetNumberOfLegs() const { return 4; }
	void Speak() { cout << "Woof" << endl; }
	void Free() { delete this; }
	static Factory<IAnimal,Dog> myFactory;
};
Factory<IAnimal,Dog> Dog::myFactory;

class Spider : public IAnimal //
{
public:
	int GetNumberOfLegs() const { return 8; }
	void Speak() { }
	void Free() { delete this; }
	static Factory<IAnimal,Spider> myFactory;
};
Factory<IAnimal,Spider> Spider::myFactory;

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 Factory<IAnimal,Horse> myFactory;
};
Factory<IAnimal,Horse> Horse::myFactory;

上面不是采用函数指针,而是每个子类采用一个静态的factory实例,由于是静态的成员,需要在类外面进行定义,否则编译将会出现unresolved externals的错误。

3.创建函数

IAnimal *CreateAnimal(std::map<string,IAnimal::SimpleBaseClassFactory *> &factories,const string &animalName)
{
	return  factories[animalName]->createInstance();
}

4.客户端使用

void main()
{

	IAnimal  *pAnimal    = NULL;
	//Register
	std::map<string,IAnimal::SimpleBaseClassFactory *>  factories;
	factories["Cat"] = &Cat::myFactory;
	factories["Dog"] = &Dog::myFactory;
	factories["Spider"] = &Spider::myFactory;
	factories["Horse"] = &Horse::myFactory;

	string animalName;
	while( pAnimal == NULL )
	{
		cout << "Type the name of an animal or 'q' to quit: ";
		cin >> animalName;

		if( animalName == "q" )
			break;

		IAnimal *pAnimal = CreateAnimal(factories,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();
	}

上面的map的创建是在主函数中,在比较复杂的场景中,可以在一个单例中创建该map,如果需要添加实例化其他的类,只需要将该类的factory添加到map中即可。

时间: 2024-10-30 00:35:48

[设计模式]两种方法实现简单工厂模式的相关文章

易学设计模式看书笔记(2) - 简单工厂模式

本文摘自易学设计模式一书 一.简单工厂模式 1.动物管理系统的例子 public interface Animal{ public void eat(); } public class Tiger implements Animal { public void eat(){ sysout.out.println("老虎会吃"); }; public void run(){ sysout.out.println("老虎会跑"); }; } public class D

iOS设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)

1. 简单工厂模式 如何理解简单工厂,工厂方法, 抽象工厂三种设计模式? 简单工厂的生活场景,卖早点的小摊贩,他给你提供包子,馒头,地沟油烙的煎饼等,小贩是一个工厂,它生产包子,馒头,地沟油烙的煎饼.该场景对应的UML图如下所示: 图1:简单工厂模式UML图 简单工厂模式的参与者: 工厂(Factory)角色:接受客户端的请求,通过请求负责创建相应的产品对象. 抽象产品(Abstract Product)角色: 是工厂模式所创建对象的父类或是共同拥有的接口.可是抽象类或接口. 具体产品(Conc

iOS常用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)

1. 简单工厂模式 如何理解简单工厂,工厂方法, 抽象工厂三种设计模式? 简单工厂方法包含:父类拥有共同基础接口,具体子类实现子类特殊功能,工厂类根据参数区分创建不同子类实例.该场景对应的UML图如下所示: 代码结构如下 Animal 类 @interface Animal :NSObject @proterty(nonatomic,strong) NSString *name; -(void)laugh; @end Dog类 @interface Dog:Animal @end Cat类 @i

iOS经常使用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)

1. 简单工厂模式 怎样理解简单工厂,工厂方法. 抽象工厂三种设计模式? 简单工厂的生活场景.卖早点的小摊贩.他给你提供包子,馒头,地沟油烙的煎饼等,小贩是一个工厂.它生产包子,馒头,地沟油烙的煎饼. 该场景相应的UML图例如以下所看到的: 图1:简单工厂模式UML图 简单工厂模式的參与者: 工厂(Factory)角色:接受client的请求,通过请求负责创建对应的产品对象. 抽象产品(Abstract Product)角色:是工厂模式所创建对象的父类或是共有的接口.但是抽象类或接口. 详细产品

&quot;围观&quot;设计模式(8)--创建型之简单工厂模式、工厂方法模式、抽象工厂模式

工厂模式的核心思想在我认为是将类创建的权利授予给工厂类,其他的类不允许创建,授予了权限的类创建好之后,需要某些的对象的时候,可以去工厂当中去取.也就是像一个工厂一样,用的人不需要关心对象怎么来的,你只需要关心怎么用就好了.工厂模式细分为三种,简单工厂.工厂方法.抽象工厂三种模式.这三种模式比较相似,往往会引发混淆,本文主要结合实际的例子去进行区分.理清三者之间的关系与适用范围. 概述 简单工厂 对于简单工厂,我个人的理解是,直接实现一个方法,要生产什么由这个方法以及传入的参数来决定. 工厂方法

设计模式(一):简单工厂模式

最近在看设计模式方面的一些的内容,发现自己以前在面向对象编程方面的能力真的是太水了,实在是还有很多东西需要学习,从这篇文章开始会将所学到的设计模式写下来,也会附上自己的理解以及相关实验代码. 首先来讲讲简单工厂模式,试着想象我们平时生活中的工厂,一个工厂通常都是只有同一种类的产品,比如说鞋子,于是这个工厂里就会生产各种不同的鞋子,像皮鞋.帆布鞋.板鞋.跑步鞋等等.客户需要某种鞋子,当然不会自己生产,肯定是让工厂生产,然后客户去取货.那么客户就要告诉工厂需要哪种鞋子,工厂生产出来给客户就行了.这就

【设计模式学习笔记】 之 简单工厂模式

 简介:工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,拒绝客服端程序员通过new创建需要的实例,并且是通过使用一个共同的接口来指向新创建的对象,即接口引用指向实现类对象,是多态的灵活运用. 举例1[未使用工厂模式]: 一个家庭中有多辆汽车,这个家庭想去出游,需要先传一个Car到Family中持有,才能出游. 首先考虑多辆汽车,都有同样的ru

[Python设计模式] 第1章 计算器——简单工厂模式

写在前面的话 """ 读书的时候上过<设计模式>这一门课,当时使用的教材是程杰老师的<大话设计模式>,使用的语言是C#,学过课程之后初期深感面向对象思想的伟大,但是很少应用到实际开发中.后来我接触了Python,现在工作中用到最多的也是Python,或许是因为Python的便利性,我写的很多脚本/程序都还是面向过程编程,缺少面向对象的思想在里边.因此,我打算重读程杰老师的<大话设计模式>并用Python进行实践. ""&

深入理解设计模式(二):简单工厂模式

本文首先概述了简单工厂模式本质及结构,揭示了简单工厂模式的应用场景和优缺点,紧接着列举出了和工厂方法模式.策略模式的异同及应用场景,最后我们给出了简单工厂模式的实现方式及注意事项. 一.什么是简单工厂模式 简单工厂模式又称为静态工厂模式,实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例.简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例. 其实就是将一个具体类的实例化交给一个静态工厂方法来执行,它不属于GOF的23种设计