动机(Motivation)

  • 在软件系统中,经常面临着创建对象的工作;由于需求的变化,需要创建的对象的具体类型经常变化。
  • 如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户和这种“具体对象创建工作”的紧耦合?

工厂方法模式是一种创建型设计模式, 其在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。

在这里插入图片描述


一、模式定义

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解耦,收到:虚函数)到子类。 ——《设计模式》GoF

二、解决方案

工厂方法模式建议使用特殊的工厂方法代替对于对象构造函数的直接调用 (即使用 new运算符)。 不用担心, 对象仍将通过 new运算符创建, 只是该运算符改在工厂方法中调用罢了。 工厂方法返回的对象通常被称作 “产品”。


三、模式结构

主要角色

  • 抽象产品(Product):定义产品的接口

  • 具体产品(Concrete Product):实现抽象产品接口的具体类

  • 抽象工厂(Creator):声明工厂方法,返回产品对象

  • 具体工厂(Concrete Creator):重写工厂方法,返回具体产品实例

在这里插入图片描述

四、代码实现


#include<iostream>
#include<memory>
#include<string>

//日志级别
enum class LogLevel {
	INFO,
	WARNING,
	ERROR
};

//抽象日志记录器
class Logger {
public:
	virtual ~Logger() = default;
	virtual void log(const std::string&message, LogLevel level) = 0;
};

//文件日志记录器
class FileLogger :public Logger {
public:
	void log(const std::string&message, LogLevel level)override {
		std::cout << "[File]" << levelToString(level) << ":" << message << std::endl;
	}
private:
	std::string levelToString(LogLevel level) {
		switch (level)
		{
		case LogLevel::INFO: return "INFO";
			break;
		case LogLevel::WARNING: return "WARNING";
			break;
		case LogLevel::ERROR: return "ERROR";
			break;
		default: return "UNKNOWN";
			break;
		}
	}
};

//控制台日志
class ConsoleLogger :public Logger {
public:
	void log(const std::string&message, LogLevel level)override {
		std::cout << "[Console]" << levelToString(level) << ":" << message << std::endl;
	}
private:
	std::string levelToString(LogLevel level) {
		switch (level)
		{
		case LogLevel::INFO: return "INFO";
			break;
		case LogLevel::WARNING: return "WARNING";
			break;
		case LogLevel::ERROR: return "ERROR";
			break;
		default: return "UNKNOWN";
			break;
		}
	}
};

//数据库日志记录
class DatabaseLogger :public Logger {
public:
	void log(const std::string&message, LogLevel level)override {
		std::cout << "[Database]" << levelToString(level) << ":" << message << std::endl;
	}
private:
	std::string levelToString(LogLevel level) {
		switch (level)
		{
		case LogLevel::INFO: return "INFO";
			break;
		case LogLevel::WARNING: return "WARNING";
			break;
		case LogLevel::ERROR: return "ERROR";
			break;
		default: return "UNKNOWN";
			break;
		}
	}
};

//抽象工厂
class LoggerFactory {
public:
	virtual ~LoggerFactory() = 0;
	virtual std::unique_ptr<Logger>createLogger() = 0;
};

//具体日志工厂
class FileLoggerFactory :public LoggerFactory {
public:
	std::unique_ptr<Logger>createLogger()override {
		return std::make_unique<FileLogger>();
	}
};

class ConsoleLoggerFactory :public LoggerFactory {
public:
	std::unique_ptr<Logger>createLogger()override {
		return std::make_unique<ConsoleLogger>();
	}
};

class DatabaseLoggerFactory :public LoggerFactory {
public:
	std::unique_ptr<Logger>createLogger()override {
		return std::make_unique<DatabaseLogger>();
	}
};

//日志管理器
class LogManager {
private:
	std::unique_ptr<LoggerFactory> factory_;
public:
	explicit LogManager(std::unique_ptr<LoggerFactory> factory)
		:factory_(std::move(factory)){}

	void setFactory(std::unique_ptr<LoggerFactory> factory) {
		factory_ = std::move(factory);
	}

	void logMessage(const std::string&message, LogLevel level) {
		auto logger = factory_->createLogger();
		logger->log(message, level);
	}
};

static void test() {
	// 创建日志管理器,使用控制台日志
	LogManager logManager(std::make_unique<ConsoleLoggerFactory>());
	logManager.logMessage("Application started", LogLevel::INFO);
	// 切换到文件日志
	logManager.setFactory(std::make_unique<FileLoggerFactory>());
	logManager.logMessage("Warning: Low memory", LogLevel::WARNING);

	// 切换到数据库日志
	logManager.setFactory(std::make_unique<DatabaseLoggerFactory>());
	logManager.logMessage("Error: Database connection failed", LogLevel::ERROR);
}

五、模板方法实现(高级技巧)



//使用模板方法的工厂实现
template<typename T>
class CreatorTemplate {
public:
	virtual ~CreatorTemplate() = default;

	//工厂方法
	std::unique_ptr<T> create() {
		return std::make_unique<T>();
	}

	//带参数的工厂方法
	template<typename... Args>
	std::unique_ptr<T> createWithArgs(Args&&... args) {
		return std::make_unique<T>(std::forward<Args>(args)...);
	}
};

//具体产品
class AdvancedProduct {
private:
	std::string name_;
	int value_;
public:
	AdvancedProduct():name_("Default"),value_(0){}
	AdvancedProduct(const std::string&name,int value)
		:name_(name),value_(value){}

	void show() {
		std::cout << "Product: " << name_ << ", Value: " << value_ << std::endl;
	}
};

static void test2() {
	CreatorTemplate<AdvancedProduct> creator;

	auto product1 = creator.create();
	product1->show();

	auto product2 = creator.createWithArgs("CustomProduct", 42);
	product2->show();
}

总结

  • Factory Method模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导致软件的脆弱。
  • Factory Method模式通过面向对象的手法,将所要创建的具体对
    象工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种紧耦合关系。
  • Factory Method模式解决“单个对象”的需求变化。缺点在于要求创建方法/参数相同。
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐