设计模式--简单工厂模式

Posted Jqivin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式--简单工厂模式相关的知识,希望对你有一定的参考价值。


简单工厂模式介绍

简单工厂模式并不属于GoF 23个经典设计模式。它的设计思想很简单。
首先,我们定义不同的具体产品类来封装不同类型的对象的相关代码。然后将这些具体产品类中的共同部分提取后封装到一个抽象产品类中。每一个具体产品类都是抽象产品类的子类。然后我们定义一个工厂类,里面封装一个创建不同产品的工厂方法(静态方法),使客户端可以传入工厂类不同的参数来创建不同的产品。
客户端想要创建 产品只需要给工厂类的静态方法提供相应的参数就可以了。

有以下几种角色:
Factory(工厂角色):工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象;在工厂类中提供了静态的工厂方法factoryMethod(),它的返回类型为抽象产品类型Product。

Product(抽象产品角色):它是工厂类所创建的所有对象的父类,封装了各种产品对象的公有方法,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂方法,因为所有创建的具体产品对象都是其子类对象。

ConcreteProduct(具体产品角色):它是简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法。

在简单工厂模式中,客户端通过工厂类来创建一个产品类的实例,而无须直接使用new关键字来创建对象,它是工厂模式家族中最简单的一员。
在这里插入图片描述

用简单工厂模式生产Audi和Benz汽车。
代码如下:

//抽象产品类
class Car
{
public:
	Car(){}
	virtual ~Car() {}
	//所有产品的公共业务方法...

	//产品的抽象方法,在子类中实现
	virtual void show() = 0;
};
//具体产品类
class Audi :public Car
{
public:
	Audi(){ cout << "construct Audi car" << endl; }
	~Audi(){ cout << "destory Audi car" << endl; }
	void show() { cout << "this is a Audi car" << endl; }
};
class Benz :public Car
{
public:
	Benz() { cout << "construct Benz car" << endl; }
	~Benz() { cout << "destory Benz car" << endl; }
	void show() { cout << "this is a Benz car" << endl; }
};
//工厂
class Factory
{
public:
	static Car* getCar(const string& name)
	{
		if (name == "Audi")
			return new Audi();
		else if (name == "Benz")
			return new Benz();
		else
		{
			return nullptr;
		}
	}
};
//客户端
int main()
{
	unique_ptr<Factory> fa(new Factory);
	unique_ptr<Car> ad(fa->getCar("Audi"));
	unique_ptr<Car> bz(fa->getCar("Benz"));

	ad->show();
	bz->show();

	return 0;
}

结果:
在这里插入图片描述
也可以改一下代码,当没有这个类型的车的时候,抛出异常。

class NoCar
{
public:
	NoCar(const string& name) { cout << "don't have "<<name <<" car" << endl; }
	~NoCar() { cout << "bye error" << endl; }
};
//工厂
class Factory
{
public:
	static Car* getCar(const string& name)
	{
		if (name == "Audi")
			return new Audi();
		else if (name == "Benz")
			return new Benz();
		else
		{
			//return nullptr;
			throw NoCar(name);
		}
	}
};
//客户端
int main()try
{
	unique_ptr<Factory> fa(new Factory);
	unique_ptr<Car> ad(fa->getCar("Audi"));
	ad->show();
	unique_ptr<Car> bm(fa->getCar("BMW"));
	bm->show();
	cout << "hello" << endl; 
	return 0;
}
catch (...) //catch(NoCar&) 只捕获NoCar异常
{
	cout << "error" << endl;
}

结果:捕获异常之后就不在进入主函数了(没有输出hello)。
在这里插入图片描述

总结

1. 优点

(1)包含必要的逻辑判断,可以根据客户端提供的参数来决定创建何种产品。
(2) 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以在一定程度减少使用者的记忆量

2. 缺点

(1)适合少量种类的产品的创建。产品种类过多会造成类过多。而且工厂类中的静态方法也会做更多的if条件判断,导致工厂类的职责过多。
(2)当系统中需要引入新产品时,由于静态工厂方法通过所传入参数的不同来创建不同的产品,这必定要修改工厂类的源代码,将违背“开闭原则”。
(3)所有的产品都由同一个工厂创建,工厂类职责较重,业务逻辑较为复杂,具体产品与工厂类之间的耦合度高,严重影响了系统的灵活性和扩展性。
开闭原则:一个软件实体应当对扩展开放,对修改关闭。即软件实体应尽量在不修改原有代码的情况下进行扩展。

3.适合场景

(1) 工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。

(2) 客户端只知道传入工厂类的参数,对于如何创建对象并不关心。

异常的处理

在这里插入图片描述

以上是关于设计模式--简单工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式学习——简单工厂模式工厂模式抽象工厂模式

设计模式之简单工厂模式

设计模式-简单工厂工厂方法模式抽象工厂模式详解

Delphi 设计模式:《HeadFirst设计模式》Delphi7代码---工厂模式之简单工厂

C#之三十八 简单工厂设计模式

设计模式之简单工厂模式