本文通过一个例子简单介绍简单工厂模式、工厂模式和抽象工厂模式。

1.简单工厂(静态)

        假如我想换个手机,换什么手机呢?可以考虑苹果或者华为手机,那我们用简单工厂模式来实现这个功能:

        我们关注的产品是手机,那生产手机的工厂有苹果,有华为,用户也不确定选哪种怎么办?这里用简单工厂模式:定义两个枚举类型,然后写一个工厂类,根据用户传入的枚举类型生产对应品牌的手机:

手机基类:

#pragma once
class MyPhone
{
public:
	MyPhone(double price);
	~MyPhone();
	double getPrice() { return m_price; }
private:
	double m_price;
};
#include "MyPhone.h"

MyPhone::MyPhone(double price) :m_price(price)
{
}
MyPhone::~MyPhone()
{
}

苹果手机:

#pragma once
#include "MyPhone.h"
class Phone_Apple:public MyPhone
{
public:
	Phone_Apple(double price);
	~Phone_Apple();
};
#include "Phone_Apple.h"
#include "stdio.h"
Phone_Apple::Phone_Apple(double price):MyPhone(price)
{
	printf("This is iPhone!");
}
Phone_Apple::~Phone_Apple()
{
}

华为手机:

#pragma once
#include "MyPhone.h"

class Phone_Huawei :public MyPhone
{
public:
	Phone_Huawei(double price);
	~Phone_Huawei();
};
#include "Phone_Huawei.h"
#include "stdio.h"
Phone_Huawei::Phone_Huawei(double price) :MyPhone(price)
{
	printf("This is HUAWEI!");
}
Phone_Huawei::~Phone_Huawei()
{
}

简单工厂类:

#pragma once
#include "MyPhone.h"
enum phoneType
{
	APPLE_Phone,
	HUAWEI_Phone
};
class SimpleFactory
{
public:
	SimpleFactory();
	~SimpleFactory();

	MyPhone* createPhone(phoneType type);
};
#include "SimpleFactory.h"
#include "Phone_Apple.h"
#include "Phone_Huawei.h"
SimpleFactory::SimpleFactory()
{
	
}
SimpleFactory::~SimpleFactory()
{
}
MyPhone* SimpleFactory::createPhone(phoneType type)
{
	MyPhone* phone = nullptr;
	switch (type)
	{
	case APPLE_Phone:
		phone = new Phone_Apple(6000);
		break;
	case HUAWEI_Phone:
		phone = new Phone_Huawei(5600);
		break;
	}
	return phone;
}

用户根据自定义类型修改创建:

	SimpleFactory* factory = new SimpleFactory();
	//用户指定要苹果
	MyPhone* phone = factory->createPhone(APPLE_Phone);
	cout << "Price: " << phone->getPrice() << endl;

    delete phone;
	delete factory;

c++设计模式三:工厂模式-LMLPHP

2.工厂模式        

        这里的工厂类似于一个手机销售店,你需要什么手机就提供什么手机,没有问题,如果用户增加了需求,想要添加三星、OPPO等,怎么办?

  1. 可以分别继承Myphone类,分别实现不同产品;
  2. 在SimpleFactory类中添加对应类别;
  3. 在createPhone方法中添加对应类别(还要引入对应的新的类和头文件);
  4. 可通过配置文件等方式准备好已有的类型供用户选择调用;

        很明显每次都要对原文件修改,如何避免呢?这里进入工厂模式:将生产手机的工厂抽象出来,然后将具体的生产厂家继承自这个抽象工厂,分别创建自己的产品:

抽象工厂类:

#pragma once
#include "MyPhone.h"
class IFactory
{
public:
	IFactory();
	~IFactory();

	virtual MyPhone* createPhone() = 0;
};

华为工厂:

#pragma once
#include "IFactory.h"
#include "MyPhone.h"
class HuaweiFactory : public IFactory
{
public:
	HuaweiFactory();
	~HuaweiFactory();
	virtual MyPhone* createPhone();
};
#include "HuaweiFactory.h"
#include "Phone_Huawei.h"
HuaweiFactory::HuaweiFactory()
{
}
HuaweiFactory::~HuaweiFactory()
{
}
MyPhone* HuaweiFactory::createPhone()
{
	MyPhone* phone = new Phone_Huawei(5600);
	return phone;
}

苹果工厂:

#pragma once
#include "IFactory.h"
#include "MyPhone.h"
class IphoneFactory :	public IFactory
{
public:
	IphoneFactory();
	~IphoneFactory();
	virtual MyPhone* createPhone();
};
#include "IphoneFactory.h"
#include "Phone_Apple.h"
IphoneFactory::IphoneFactory()
{
}
IphoneFactory::~IphoneFactory()
{
}
MyPhone* IphoneFactory::createPhone()
{
	MyPhone* phone = new Phone_Apple(6000);
	return phone;
}
	//3.2 工厂模式
	IFactory* factory = new IphoneFactory();
	MyPhone* phone = factory->createPhone();
	cout << "Price: " << phone->getPrice() << endl;

	IFactory* factory1 = new HuaweiFactory();
	MyPhone* phone1 = factory1->createPhone();
	cout << "Price: " << phone1->getPrice() << endl;

	delete phone;
	delete phone1;
	delete factory;
	delete factory1;

c++设计模式三:工厂模式-LMLPHP

 3.抽象工厂模式

        这时,如果用户需要增加产品类型,比如华为的平板、苹果的平板怎么办?这就要引入抽象工厂模式了。 

  1. 将产品类进行抽象(这里可能会涉及多种产品);
  2. 写出具体的产品类;
  3. 将工厂类进行抽象;
  4. 具体工厂生产对应的产品(一个工厂可以生产自己品牌的多种产品)

 在原来代码基础上进行修改:

产品抽象类:

#pragma once
class MyPhone
{
public:
	MyPhone(double price);
	~MyPhone();
	double getPrice() { return m_price; }
private:
	double m_price;
};

class MyPad
{
public:
	MyPad(double price);
	~MyPad();
	double getPrice() { return m_price; }
private:
	double m_price;
};

苹果产品类:

#pragma once
#include "MyPhone.h"
class Phone_Apple:public MyPhone
{
public:
	Phone_Apple(double price);
	~Phone_Apple();
};
class Pad_Apple :public MyPad
{
public:
	Pad_Apple(double price);
	~Pad_Apple();
};

华为产品类:

#pragma once
#include "MyPhone.h"

class Phone_Huawei :public MyPhone
{
public:
	Phone_Huawei(double price);
	~Phone_Huawei();
};
class Pad_Huawei :public MyPad
{
public:
	Pad_Huawei(double price);
	~Pad_Huawei();
};

抽象工厂类:

#pragma once
#include "MyPhone.h"
class IFactory
{
public:
	IFactory();
	~IFactory();

	virtual MyPhone* createPhone() = 0;
	virtual MyPad* createPad() = 0;
}

具体工厂类:

#pragma once
#include "IFactory.h"
#include "MyPhone.h"
#include "Phone_Apple.h"
class IphoneFactory :	public IFactory
{
public:
	IphoneFactory();
	~IphoneFactory();
	virtual MyPhone* createPhone(){
		MyPhone* phone = new Phone_Apple(6000);
		return phone;
	}
	virtual MyPad* createPad() {
		MyPad* phone = new Pad_Apple(4900);
		return phone;
	}
};
#pragma once
#include "IFactory.h"
#include "MyPhone.h"
#include "Phone_Huawei.h"
class HuaweiFactory : public IFactory
{
public:
	HuaweiFactory();
	~HuaweiFactory();
	virtual MyPhone* createPhone() {
		MyPhone* phone = new Phone_Huawei(5600);
		return phone;
	}
	virtual MyPad* createPad() {
		MyPad* phone = new Pad_Huawei(4600);
		return phone;
	}
};

调用:

	//3.3 抽象工厂模式
	IFactory* factory = new HuaweiFactory();
	MyPad* pad = factory->createPad();
	cout << "Price: " << pad->getPrice() << endl;
	MyPhone* phone = factory->createPhone();
	cout << "Price: " << phone->getPrice() << endl;
	delete pad;
	delete phone;
	delete factory;

4.总结对比

 三种方法使用选择:

        分别理解三种模式并不困难,关键就在于根据实际问题实际情况选用不同的模式,先总结如下思考方式,供参考:

  •         当产品类型固定时可选择简单工厂模式(这里可以认为是零维的,即不用考虑其他维度);
  •         当产品涉及到不同厂商时,将工厂抽象化,不同厂商实现大厂的接口(这里可以认为是一维的,除了产品自身还需考虑厂商问题);
  •         当涉及到不同厂商的不同产品时,将工厂和产品分别抽象化(这里可以认为是二维的,考虑产品的种类以及厂商问题);

 总之要尽量满足OOP七大原则:

  • 开闭原则: 一个软件的实体应当对扩展开放,对修改关闭
  • 依赖倒转原则: 要针对接口编程,不要针对实现编程
  • 迪米特法则:只与你直接的朋友通信,而避免和陌生人通信

   三种方式的对比:

简单(静态)工厂模式:

        用来生产同一等级结构中的任意产品(对于增加新的产品,需要修改已有代码;

工厂方法模式:

        用来生产同一等级结构中的固定产品(支持增加任意产品)

        优点:

  • 你可以避免创建者和具体产品之间的紧密耦合。
  • 单一职责原则。你可以将产品创建代码放在程序的单一位置,从而使得代码更容易维护。
  • 开闭原则。无需更改现有客户端代码,你就可以在程序中引入新的产品类型。

      缺点:

  • 应用工厂方法模式需要引入许多新的子类,代码可能会因此变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。

抽象工厂模式:

         围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。

        优点:

  • 应用工厂方法模式需要引入许多新的子类,代码可能会因此变得更复杂。最好的情况是将该模式引入创建者类的现有层次结构中。

        缺点:

  •   由于采用该模式需要向应用中引入众多接口和类,代码可能会比之前更加复杂。

参考文献:【精选】设计模式之工厂模式(简单工厂、工厂方法、抽象工厂)_简单工厂模式 抽象工厂模式-CSDN博客1. 工厂方法模式(Factory Method) (yuque.com)2. 抽象工厂模式(Abstract Factory) (yuque.com)

10-29 19:21