设计模式之美(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-工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之美(c++)-笔记-56-观察者模式

设计模式之美(c++)-笔记-48-代理模式

设计模式之美(c++)-笔记-48-代理模式

设计模式之美(c++)-笔记-10-组合

设计模式之美(c++)-笔记-46-建造者模式

设计模式之美(c++)-笔记-09-接口