一、工厂模式简介
工厂方法模式(Factory Method Pattern)同样属于类的创建型模式又被称为多态工厂模式 。工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作(延迟)放到子类当中实现。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。(工厂模式生产专一产品)
GoF一书对工厂方法模式的介绍
二、工厂方法模式的用处
开闭原则:它允许在不修改现有客户端代码的前提下添加新类型。客户端代码与具体的产品类解耦,能够独立于产品的创建与实现。
单一职责原则:通过定义一个工厂接口,可以创建一个对应的产品族的多个实现,每个实现专责创建特定类型的产品。
代码重用:通过使用工厂方法,可以根据不同条件创建不同的产品,从而实现代码的重用。
可扩展性:它允许系统在不修改原有代码的基础上进行扩展。如果你需要创建一个新产品类型,你只需要添加一个实现类和一个工厂方法。
可插拔性:工厂方法可以让你在不更改使用工厂方法的代码的情况下,替换掉工厂的具体产品类。
例如,如果你开发了一个游戏,游戏中有多种角色,你可以为每种角色定义一个工厂类,每个工厂类负责创建对应角色的实例。当需要添加新的角色时,添加一个新的工厂类和角色类即可,不需要修改已有的代码。
工厂方法模式通常用于创建多个产品家族中的一种,每个家族都有相同性质但不同类型的产品。例如,对于不同的交通工具,可以使用不同的工厂来创建交通工具的不同子类。
因此工厂方法模式适用于生产专一的产品。
三、工厂方法模式的设计方法
1)简单工厂模式
通过简单工厂模式设计了水果工厂生产七种水果,每次新增水果种类都需要修改Factory类,因此不适用现代代码。
simpleFactory.cpp
#include <iostream>
#include <cstring>using namespace std;class Fruit
{
public:virtual void getFruit() = 0;protected:
private:
};class Banana : public Fruit
{
public:virtual void getFruit(){std::cout << "香蕉 " << std::endl;}
protected:
private:
};class Apple : public Fruit
{
public:virtual void getFruit(){std::cout << "苹果 " << std::endl;}
protected:
private:
};class Tangerine : public Fruit
{
public:virtual void getFruit(){std::cout << "橘子 " << std::endl;}
protected:
private:
};class Orange : public Fruit
{
public:virtual void getFruit(){std::cout << "橙子 " << std::endl;}
protected:
private:
};class Watermelon : public Fruit
{
public:virtual void getFruit(){std::cout << "西瓜 " << std::endl;}
protected:
private:
};class Cherry : public Fruit
{
public:virtual void getFruit(){std::cout << "樱桃 " << std::endl;}
protected:
private:
};class Peach : public Fruit
{
public:virtual void getFruit(){std::cout << "桃子 " << std::endl;}
protected:
private:
};class Factory
{
public:Fruit *create(const char *type){if (strcmp(type, "banana") == 0){return new Banana; }else if (strcmp(type, "apple") == 0){return new Apple;}else if (strcmp(type, "peach") == 0){return new Peach;}else if (strcmp(type, "tangerine") == 0){return new Tangerine;}else if (strcmp(type, "orange") == 0){return new Orange;}else if (strcmp(type, "watermelon") == 0){return new Watermelon;}else if (strcmp(type, "cherry") == 0){return new Cherry;}else{printf("不支持的水果类型\n" ) ;return nullptr;}}
protected:
private:};void main001()
{Factory *factory = new Factory;Fruit *fruit = nullptr;//工厂生产水果fruit = factory->create("banana");fruit->getFruit();delete fruit;fruit = factory->create("apple");fruit->getFruit();delete fruit;fruit = factory->create("peach");fruit->getFruit();delete fruit;fruit = factory->create("tangerine");fruit->getFruit();delete fruit;fruit = factory->create("orange");fruit->getFruit();delete fruit;fruit = factory->create("watermelon");fruit->getFruit();delete fruit;fruit = factory->create("cherry");fruit->getFruit();delete fruit;//注销工厂delete factory;factory = nullptr;return ;
}int main(){//开工干活main001();return 0;
}
运行效果
简单工厂模式违反了开放封闭原则,违背高内聚的目标,因此不适用于实际应用,仅适合了解和教学。
2)工厂方法模式
工厂方法模式中,每新增一个水果种类,需要新增一个该水果工厂(专一加工),这样的设计模式只需要在原来的基础上增加新的水果和水果工厂即可,而不需要修改代码,符合高内聚,低耦合的目标,且不违反开放封闭原则。
factory.cpp
#include <iostream>using namespace std;class Fruit
{
public:virtual void getProduct() = 0;virtual ~Fruit() = default;
};class Banana : public Fruit
{
public:void getProduct() override{std::cout << "香蕉 " << std::endl;}
};class Apple : public Fruit
{
public:void getProduct() override{std::cout << "苹果 " << std::endl;}
};class Tangerine : public Fruit
{
public:void getProduct() override{std::cout << "橘子 " << std::endl;}
};class Orange : public Fruit
{
public:void getProduct() override{std::cout << "橙子 " << std::endl;}
};class Watermelon : public Fruit
{
public:void getProduct() override{std::cout << "西瓜 " << std::endl;}
};class Cherry : public Fruit
{
public:void getProduct() override{std::cout << "樱桃 " << std::endl;}
};class Peach : public Fruit
{
public:void getProduct() override{std::cout << "桃子 " << std::endl;}
};// 新增水果产品
class Pear : public Fruit
{
public:void getProduct() override{std::cout << "新款水果——梨 " << std::endl;}
};// 抽象工厂
class AbstractFactory
{
public:virtual Fruit* createProduct() = 0;virtual ~AbstractFactory() = default;
};// 具体工厂
class BananaFactory : public AbstractFactory
{
public:Fruit* createProduct() override{return new Banana;}
};class AppleFactory : public AbstractFactory
{
public:Fruit* createProduct() override{return new Apple;}
};class TangerineFactory : public AbstractFactory
{
public:Fruit* createProduct() override{return new Tangerine;}
};class OrangeFactory : public AbstractFactory
{
public:Fruit* createProduct() override{return new Orange;}
};class WatermelonFactory : public AbstractFactory
{
public:Fruit* createProduct() override{return new Watermelon;}
};class CherryFactory : public AbstractFactory
{
public:Fruit* createProduct() override{return new Cherry;}
};class PeachFactory : public AbstractFactory
{
public:Fruit* createProduct() override{return new Peach;}
};// 新增 梨 工厂
class PearFactory : public AbstractFactory
{
public:Fruit* createProduct() override{return new Pear;}
};void doWorking()
{AbstractFactory* factory = nullptr;Fruit* fruit = nullptr;// 各种水果工厂和产品创建factory = new BananaFactory;fruit = factory->createProduct();fruit->getProduct();delete fruit;delete factory;factory = new AppleFactory;fruit = factory->createProduct();fruit->getProduct();delete fruit;delete factory;factory = new TangerineFactory;fruit = factory->createProduct();fruit->getProduct();delete fruit;delete factory;factory = new OrangeFactory;fruit = factory->createProduct();fruit->getProduct();delete fruit;delete factory;factory = new WatermelonFactory;fruit = factory->createProduct();fruit->getProduct();delete fruit;delete factory;factory = new CherryFactory;fruit = factory->createProduct();fruit->getProduct();delete fruit;delete factory;factory = new PeachFactory;fruit = factory->createProduct();fruit->getProduct();delete fruit;delete factory;factory = new PearFactory;fruit = factory->createProduct();fruit->getProduct();delete fruit;delete factory;
}int main()
{//开工干活doWorking();return 0;
}
运行效果
四、工厂模式的流程
工厂的主要组成部分
- 产品接口(Product):定义了工厂方法所创建的对象的接口。
- 具体产品(ConcreteProduct):实现了产品接口的具体类。
- 工厂接口(Creator):声明了工厂方法,它返回一个产品对象的接口。
- 具体工厂(ConcreteCreator):实现了工厂接口,并返回具体产品的实例。
工厂的工作流程
- 客户端:依赖于工厂接口来创建产品对象。
- 工厂方法:定义了创建产品的接口。
- 具体工厂:实现工厂方法,返回具体的产品实例。
- 具体产品:实现产品接口的类,表示实际的对象。
五、总结
工厂方法模式允许一个类的实例化由子类来决定。通过将对象的创建交给子类实现,提供了一种灵活的对象创建机制,符合开闭原则(对扩展开放,对修改关闭),使系统具有更好的可扩展性。但工厂方法模式引入了额外的工厂类和产品类,使得系统结构变得复杂。且难以增加新的产品,如果产品种类增加,可能需要增加工厂接口或具体工厂类,可能导致较多的代码增加。