工厂模式用于隔离类对象的使用者和具体类型之间的耦合关系,通过虚函数的方法将创建具体对象的动作延迟到子类,从而实现扩展而非更改的策略。
![](https://img.haomeiwen.com/i20369022/d6e428b9e0bd9b53.png)
如上图所以,产品和工厂作为抽象类,应该是稳定的,而具体类和具体的工厂可能会随着具体业务需求进行扩展,实际工程中并不鼓励修改。
#pragma once
#ifndef FACTORY_H
#define FACTORY_H
#include<iostream>
// 产品抽象基类
class Language {
public:
virtual void Speak() = 0;
virtual ~Language() {}
};
// 工厂基类
class LanguageFactory
{
public:
virtual Language* SpeakLanguage() = 0;
virtual ~LanguageFactory() {}
};
// 产品子类
class Chinese: public Language
{
public:
void Speak()
{
std::cout << "Speaking Chinese! \n" << std::endl;
}
};
class English : public Language
{
void Speak()
{
std::cout << "Speaking English! \n" << std::endl;
}
};
class Japanese : public Language
{
void Speak()
{
std::cout << "Speaking Japanese! \n" << std::endl;
}
};
// 工厂子类
class ChineseFactory : public LanguageFactory {
public:
virtual Language* SpeakLanguage()
{
return new Chinese();
}
};
class EnglishFactory : public LanguageFactory {
public:
virtual Language* SpeakLanguage()
{
return new English();
}
};
class JapaneseFactory : public LanguageFactory {
public:
virtual Language* SpeakLanguage()
{
return new Japanese();
}
};
class StudySpeak
{
public:
StudySpeak(LanguageFactory* _factory)
{
this->factory = _factory;
}
~StudySpeak();
private:
LanguageFactory* factory;
};
class Study {
private:
LanguageFactory* factory;
public:
Study(LanguageFactory* _factory)
{
this->factory = _factory;
}
void DailyStudy()
{
Language* lang = factory->SpeakLanguage();
lang->Speak();
}
};
#endif // !FACTORY_H
上述代码中,language类是product,LanguageFactory类是Creator,Chinese类、English类、Japanese类是concreteProduct,ChineseFactory类、EnglishFactory类、JapeneseFactory类是concreteCreator。
#include "factory.h"
#include <iostream>
int main()
{
LanguageFactory* factory = new ChineseFactory();
Study s(factory);
s.DailyStudy();
return 0;
}
执行效果如下:
![](https://img.haomeiwen.com/i20369022/001e394c022713f1.png)
上述实现只是一种众多方法中的一种,此外还可以用如下方式进行实现:
1、可以将Creator类声明为具体类并提供一个缺省的实现。
// 工厂基类
class LanguageFactory
{
public:
virtual Language* SpeakLanguage()
{
return new Chinese();
}
virtual ~LanguageFactory() {}
};
缺省调用Chinese类。
2、参数化工厂方法
参数化采用一个标识将被创建的对象种类的参数。
// 参数化工厂
class LanguageFactory{
public:
virtual Language* SpeakLanguage(std::string language);
};
Language* LanguageFactory::SpeakLanguage(std::string language)
{
if (language == "china") return new Chinese();
if (language == "english") return new English();
if (language == "japen") return new Japanese();
return 0;
}
3、使用模板以避免创建子类
有的时候可能不想为了具体的Product对象而创建creator的子类,在C++中可以提供一个Creator的模板子类,它使用Product类作为模板参数。
// 工厂基类
class LanguageFactory
{
public:
virtual Language* SpeakLanguage() = 0;
virtual ~LanguageFactory() {}
};
template <class TheLanguage>
class StandardLanguage:public LanguageFactory
{
public:
virtual Language* SpeakLanguage();
};
template <class TheLanguage>
Language* StandardLanguage<TheLanguage>::SpeakLanguage()
{
return new TheLanguage;
}
StandardLanguage<Chinese> myChinese;
函数调用结果如下:
![](https://img.haomeiwen.com/i20369022/7f056b64f262aaa6.png)
最好总结下使用Factory Method模式的场景:
1、当一个类不知道或者无法完全确定所必须创建的对象类型的时候;
这时候代码展示出扩展而非更改;
2、当一个类希望由它的子类来指定它所创建的对象类型的时候;
3、当类就创建对象的职责委托给多个子类中的一个,并且希望子类代理这一信息局部化的时候。
注:本文参考了《设计模式 可复用面向对象软件的基础》中的3.3节。
网友评论