一、概述
定义一个工厂类,工厂类中实现一个方法,此方法根据不同的参数返回不同的类。就是使用了C++多态的特性,将存在继承关系的类,通过一个工厂类创建对应的子类(派生类)对象。
结构组成:
-
产品:将会对接口进行声明。对于所有由创建者及其子类构建的对象,这些接口都是通用的。
-
具体产品:是产品接口的不同实现。
-
创建者:类声明返回产品对象的工厂方法。该方法的返回对象类型必须与产品接口相匹配。 你可以将工厂方法声明为抽象方法,强制要求每个子类以不同方式实现该方法。或者,你也可以在基础工厂方法中返回默认产品类型。注意,尽管它的名字是创建者,但他最主要的职责并不是创建产品。一般来说,创建者类包含一些与产品相关的核心业务逻辑。工厂方法将这些逻辑处理从具体产品类中分离出来。
-
具体创建者:将会重写基础工厂方法,使其返回不同类型的产品。注意,并不一定每次调用工厂方法都会创建新的实例。工厂方法也可以返回缓存、对象池或其他来源的已有对象。
二、适用场景
-
无法预知对象确切类别及其依赖关系时。
-
希望用户能扩展你软件库或框架的内部组件
-
希望复用现有对象来节省系统资源,而不是每次都重新创建对象,可使用工厂方法。
-
工厂类负责创建的对象比较少。
-
客户端只知道传入工厂类的参数,对于如何创建对象不关心。
三、优缺点
优点:
- 避免创建者和具体产品之间的紧密耦合。
- 单一职责原则。你可以将产品创建代码放在程序的单一位置,从而使得代码更容易维护。
- 开闭原则。无需更改现有客户端代码,你就可以在程序中引入新的产品类型。
缺点:
4. 想要增加新的产品类时需要修改源代码,不符合开闭原则。
5. 工厂类中集中了所有产品类的创建逻辑,如果这个类发生了问题。整个系统都要受到影响。
6. 工厂类集中了所有产品类的创建逻辑,如果产品量较大,会使得工厂类变的非常臃肿。
7. 应用工厂方法模式需要引入许多新的子类,代码可能会因此变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。
四、实例
#include <iostream>
#include<string>
#include <memory>
using namespace std;
// 抽象产品类 电影
class Movie{
public:
virtual string get_a_movie() = 0;
};
// 具体产品类 电影::国产电影
class ChineseMovie:public Movie{
public:
string get_a_movie() override{
return "《让子弹飞》";
}
};
// 具体产品类 电影::日本电影
class JapaneseMovie:public Movie{
public:
string get_a_movie() override{
return "《千与千寻》";
}
};
// 具体产品类 电影::美国电影
class AmericanMovie : public Movie {
public:
string get_a_movie() override {
return "《钢铁侠》";
}
};
//抽象工厂类,生产电影
class Factory{
public:
virtual shared_ptr<Movie> get_movie() = 0;
};
具体工厂类 中国生产者
class ChineseProducer:public Factory{
public:
shared_ptr<Movie>get_movie()override
{
return make_shared<ChineseMovie>();
}
};
具体工厂类 日本生产者
class JapaneseProducer:public Factory{
public:
shared_ptr<Movie>get_movie()override{
return make_shared<JapaneseMovie>();
}
};
// 具体工厂类 美国生产者
class AmericanProducer:public Factory{
public:
shared_ptr<Movie>get_movie()override
{
return make_shared<AmericanMovie>();
}
};
int main()
{
shared_ptr<Factory> factory;
shared_ptr<Movie>produce;
string conf = "china";
if (conf == "china") {
factory = make_shared<ChineseProducer>();
} else if (conf == "Japan") {
factory = make_shared<JapaneseProducer>();
} else if (conf == "America") {
factory = make_shared<AmericanProducer>();
} else {
cout << "error conf" << std::endl;
}
produce = factory->get_movie();
cout<< "获取一部电影: " <<produce->get_a_movie()<< std::endl;
}