工厂方法定义
在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型
工厂方法优缺点
优点
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。
灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。 - 典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。
缺点
- 类的个数容易过多,增加复杂度
- 增加了系统的抽象性和理解难度
- 抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。
工厂方法应用场景
- 当你在编写代码的过程中,如果无法预知对象确切类别及其依赖关系时,可使用工厂方法。
- 如果你希望用户能扩展你软件库或框架的内部组件,可使用工厂方法。
- 如果你希望复用现有对象来节省系统资源,而不是每次都重新创建对象,可使用工厂方法。
工厂方法的结构和实现
结构
- 产品(Product)将会对接口进行声明。对于所有由创建者及其子类构建的对象,这些接口都是通用的。
- 具体产品(Concrete Products)是产品接口的不同实现。
- 创建者(Creator)类声明返回产品对象的工厂方法。该方法的返回对象类型必须与产品接口相匹配。 你可以将工厂方法声明为抽象方法,强制要求每个子类以不同方式实现该方法。或者,你也可以在基础工厂方法中返回默认产品类型。注意,尽管它的名字是创建者,但他最主要的职责并不是创建产品。一般来说,创建者类包含一些与产品相关的核心业务逻辑。工厂方法将这些逻辑处理从具体产品类中分离出来。打个比方,大型软件开发公司拥有程序员培训部门。但是,这些公司的主要工作还是编写代码,而非生产程序员。
- 具体创建者(Concrete Creators) 将会重写基础工厂方法,使其返回不同类型的产品。注意,并不一定每次调用工厂方法都会创建新的实例。工厂
方法也可以返回缓存、对象池或其他来源的已有对象。
实现
Product.h:
#ifndef PRODUCT_H_
#define PRODUCT_H_
#include <string>
// 抽象产品类 电影
class Movie {
public:
virtual std::string get_a_movie() = 0;
};
#endif // PRODUCT_H_
ConcreteProduct.h:
#ifndef CONCRETE_PRODUCT_H_
#define CONCRETE_PRODUCT_H_
#include <iostream>
#include <string>
#include "Product.h"
// 具体产品类 电影::国产电影
class ChineseMovie : public Movie {
public:
std::string get_a_movie() override {
return "《让子弹飞》";
}
};
// 具体产品类 电影::日本电影
class JapaneseMovie : public Movie {
public:
std::string get_a_movie() override {
return "《千与千寻》";
}
};
// 具体产品类 电影::美国电影
class AmericanMovie : public Movie {
public:
std::string get_a_movie() override {
return "《钢铁侠》";
}
};
#endif // CONCRETE_PRODUCT_H_
Creator.h:
#ifndef CREATOR_H_
#define CREATOR_H_
#include "Product.h"
// 抽象工厂类 生产电影
class Factory {
public:
virtual std::shared_ptr<Movie> get_movie() = 0;
};
#endif // CREATOR_H_
ConcreteCreator.h:
#ifndef CONCRETE_CREATOR_H_
#define CONCRETE_CREATOR_H_
#include <memory>
#include "Creator.h"
#include "ConcreteProduct.h"
// 具体工厂类 中国生产者
class ChineseProducer : public Factory {
public:
std::shared_ptr<Movie> get_movie() override {
return std::make_shared<ChineseMovie>();
}
};
// 具体工厂类 日本生产者
class JapaneseProducer : public Factory {
public:
std::shared_ptr<Movie> get_movie() override {
return std::make_shared<ChineseMovie>();
}
};
// 具体工厂类 美国生产者
class AmericanProducer : public Factory {
public:
std::shared_ptr<Movie> get_movie() override {
return std::make_shared<ChineseMovie>();
}
};
#endif // CONCRETE_CREATOR_H_
main.cpp:
#include "ConcreteCreator.h"
int main() {
system("chcp 65001");
std::shared_ptr<Factory> factory;
std::shared_ptr<Movie> product;
// 这里假设从配置中读到的是Chinese(运行时决定的)
std::string conf = "China";
// 程序根据当前配置或环境选择创建者的类型
if (conf == "China") {
factory = std::make_shared<ChineseProducer>();
} else if (conf == "Japan") {
factory = std::make_shared<JapaneseProducer>();
} else if (conf == "America") {
factory = std::make_shared<AmericanProducer>();
} else {
std::cout << "error conf" << std::endl;
}
product = factory->get_movie();
std::cout << "获取一部电影: " << product->get_a_movie() << std::endl;
system("pause");
}