设计模式之美(c++)-笔记-44-工厂模式
Posted 欢乐的企鹅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之美(c++)-笔记-44-工厂模式相关的知识,希望对你有一定的参考价值。
当创建逻辑比较复杂,是一个“大工程”的时候,我们就考虑使用工厂模式,封装对象的创建过程,将对象的创建和使用相分离。何为创建逻辑比较复杂呢?我总结了下面两种情况。
第一种情况:类似规则配置解析的例子,代码中存在 if-else 分支判断,动态地根据不同的类型创建不同的对象。针对这种情况,我们就考虑使用工厂模式,将这一大坨 if-else 创建对象的代码抽离出来,放到工厂类中。
还有一种情况,尽管我们不需要根据不同的类型创建不同的对象,但是,单个对象本身的创建过程比较复杂,比如前面提到的要组合其他类对象,做各种初始化操作。在这种情况下,我们也可以考虑使用工厂模式,将对象的创建过程封装到工厂类中。
对于第一种情况,当每个对象的创建逻辑都比较简单的时候,我推荐使用简单工厂模式,将多个对象的创建逻辑放到一个工厂类中。当每个对象的创建逻辑都比较复杂的时候,为了避免设计一个过于庞大的简单工厂类,我推荐使用工厂方法模式,将创建逻辑拆分得更细,每个对象的创建逻辑独立到各自的工厂类中。同理,对于第二种情况,因为单个对象本身的创建逻辑就比较复杂,所以,我建议使用工厂方法模式。
除了刚刚提到的这几种情况之外,如果创建对象的逻辑并不复杂,那我们就直接通过 new 来创建对象就可以了,不需要使用工厂模式。
现在,我们上升一个思维层面来看工厂模式,它的作用无外乎下面这四个。这也是判断要不要使用工厂模式的最本质的参考标准。
封装变化:创建逻辑有可能变化,封装成工厂类之后,创建逻辑的变更对调用者透明。
代码复用:创建代码抽离到独立的工厂类之后可以复用。
隔离复杂性:封装复杂的创建逻辑,调用者无需了解如何创建对象。
控制复杂度:将创建代码抽离出来,让原本的函数或类职责更单一,代码更简洁。
#define ENTER_MODULE_44_NAMESPACE_PLUS namespace NAMESPACE_MODULE_44_PLUS{
#define LEAVE_MODULE_44_NAMESPACE_PLUS }
ENTER_MODULE_44_NAMESPACE_PLUS
struct RuleConfig
{
};
//interface
struct IRuleConfigParser
{
virtual RuleConfig parse(string context) = 0;
};
class JsonRuleConfigParser : public IRuleConfigParser
{
public:
RuleConfig parse(string context)
{
cout << "JsonRuleConfigParser::parse" << endl;
return RuleConfig();
}
};
class XmlRuleConfigParser : public IRuleConfigParser
{
public:
RuleConfig parse(string context)
{
cout << "XmlRuleConfigParser::parse" << endl;
return RuleConfig();
}
};
class YamlRuleConfigParser : public IRuleConfigParser
{
public:
RuleConfig parse(string context)
{
cout << "YamlRuleConfigParser::parse" << endl;
return RuleConfig();
}
};
class PropertiesRuleConfigParser : public IRuleConfigParser
{
public:
RuleConfig parse(string context)
{
cout << "PropertiesRuleConfigParser::parse" << endl;
return RuleConfig();
}
};
class RuleConfigParserFactory {
public:
static IRuleConfigParser* createParser(string configFormat) {
IRuleConfigParser* parser = nullptr;
if ("json" == configFormat) {
parser = new JsonRuleConfigParser();
}
else if ("xml" == configFormat) {
parser = new XmlRuleConfigParser();
}
else if ("yaml" == configFormat) {
parser = new YamlRuleConfigParser();
}
else if ("properties" == configFormat) {
parser = new PropertiesRuleConfigParser();
}
return parser;
}
};
//工厂类升级(工厂返回缓存对象)
class RuleConfigParserFactoryPlus {
public:
static IRuleConfigParser* createParser(string configFormat) {
if (cachedParsers.empty())
{
cachedParsers.insert(make_pair("json", new JsonRuleConfigParser()));
cachedParsers.insert(make_pair("xml", new XmlRuleConfigParser()));
cachedParsers.insert(make_pair("yaml", new YamlRuleConfigParser()));
cachedParsers.insert(make_pair("properties", new PropertiesRuleConfigParser()));
}
auto it = cachedParsers.find(configFormat);
return (it != cachedParsers.end())? it->second : nullptr;
}
private:
static map<string, IRuleConfigParser*> cachedParsers;
};
map<string, IRuleConfigParser*> RuleConfigParserFactoryPlus::cachedParsers;
struct InvalidRuleConfigException
{
InvalidRuleConfigException(string msg) { this->msg = msg; }
string msg;
};
class RuleConfigSource {
public:
RuleConfig load(string ruleConfigFilePath) {
string ruleConfigFileExtension = getFileExtension(ruleConfigFilePath);
IRuleConfigParser* parser =
RuleConfigParserFactoryPlus::createParser(ruleConfigFileExtension);
if (parser == nullptr) {
throw new InvalidRuleConfigException(
"Rule config file format is not supported: " + ruleConfigFilePath);
}
string configText = "";
//从ruleConfigFilePath文件中读取配置文本到configText中
RuleConfig ruleConfig = parser->parse(configText);
return ruleConfig;
}
private:
string getFileExtension(string filePath) {
//...解析文件名获取扩展名,比如rule.json,返回json
return "json";
}
};
int main()
{
RuleConfigSource config;
config.load("xxx.json");
return 0;
}
LEAVE_MODULE_44_NAMESPACE_PLUS
以上是关于设计模式之美(c++)-笔记-44-工厂模式的主要内容,如果未能解决你的问题,请参考以下文章