23种设计模式(二)抽象工厂模式

一、抽象工厂模式

        抽象工厂模式(Abstract Factory Pattern)隶属于设计模式中的创建型模式,用于产品族的构建。是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂是指当有多个抽象角色时使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下, 创建多个产品族中的产品对象。

        工厂模式中的每一个形态都是针对一定问题的解决方案,工厂方法针对的是多个产品系列结构;而抽象工厂模式针对的是多个产品族结构,一个产品族内有多个产品系列。

提供一个创建一系列相互依赖对象的接口,而无需指定它们具体的类。主要解决接口问题的选择


二、模式的组成

        抽像工厂模式主要由四个部分组成:抽象工厂角色、具体工厂角色, 抽象产品角色,具体产品角色。

组成作用

抽象工厂角色(AbstrctFactory)

声明了一组用于创建产品对象的方法,每个方法对应一种产品类型。抽象工厂可以是接口或抽象类。

具体工厂角色

(ChinaFactory、EgyptFactory)

实现了抽象工厂接口,负责创建具体产品对象的实例

抽象产品角色

(AbstrctWatermelon、AbstrctOrange)

定义了一组产品对象的共同接口或抽象类,描述了产品对象的公共方法。

具体产品角色

(ChinaWatermelon、ChinaOrange、EgyptWatermelon、EgyptOrange)

实现了抽象产品接口,定义了具体产品的特定行为和属性。


三、创建方法及代码实现

        抽象工厂模式有四部分:抽象工厂角色、具体工厂角色, 抽象产品角色,具体产品角色,可以将抽象工厂角色、具体工厂角色分为一部分,抽象产品角色,具体产品分为一部分。

        举个例子,一个汽车厂,在创建汽车时,首先需要有图纸,工厂才能更具图纸去创建相应的材料,但在拥有图纸之前,我们需要一个工程师去构建图纸,相应的工程师绘制相应的图纸,冰箱的工程师就绘制冰箱的图纸,汽车的工程师就绘制汽车的图纸。

这里举的例子中的图纸就是抽象工厂模式中的具体产品角色,而工程师就是模式中的抽象产品角色

根据抽象工厂模式的思想,实现该图:

图中,我们可简要分析一下,具体产品有中国西瓜、中国橙子、埃及西瓜、埃及橙子,在产品中,可分为两种产品类型:西瓜和橙子,那么我们可以将其实现为抽象产品。

注:在代码实现中,为简洁明了,使用了在构造函数与析构函数中打印输出的方式展现,各种产品的特性均为体现,读者可自行添加产品细节。


实现步骤及代码如下:

1、创建抽象产品

将西瓜与橙子分别实现出来,为不同的具体产品提供一个公共的接口:

//抽象水果类:西瓜
class AbstrctWatermelon {
public:
	virtual void Watermelon() = 0;
	AbstrctWatermelon() {
		std::cout << "抽象西瓜的构造函数被调用!" << std::endl;
	}
	~AbstrctWatermelon() {
		std::cout << "抽象西瓜的析构函数被调用!" << std::endl;
	}
};
//抽象水果类:橙子
class AbstrctOrange {
public:
	virtual void Orange() = 0;
	AbstrctOrange() {
		std::cout << "抽象橘子的构造函数被调用!" << std::endl;
	}
	~AbstrctOrange() {
		std::cout << "抽象橘子的析构函数被调用!" << std::endl;
	}
};

2、创建具体产品

根据1中提供的接口,分别实现具体产品中国西瓜、中国橙子、埃及西瓜、埃及橙子

//具体产品:中国西瓜
class ChinaWatermelon :public AbstrctWatermelon {
public:
	virtual void Watermelon() {
		std::cout << "中国西瓜真甜,好吃!" << std::endl;
	}
	ChinaWatermelon() {
		std::cout << "中国西瓜的构造函数被调用!" << std::endl;
	}
	~ChinaWatermelon() {
		std::cout << "中国西瓜的析构函数被调用!" << std::endl;
	}
};
//具体产品:中国橙子
class ChinaOrange :public AbstrctOrange {
public:
	virtual void Orange() {
		std::cout << "中国橙子真甜,好吃!" << std::endl;
	}
	ChinaOrange() {
		std::cout << "中国橙子的构造函数被调用!" << std::endl;
	}
	~ChinaOrange() {
		std::cout << "中国橙子的析构函数被调用!" << std::endl;
	}
};
//具体产品:埃及西瓜
class EgyptWatermelon :public AbstrctWatermelon {
public:
	virtual void Watermelon()
	{
		std::cout << "埃及西瓜不好吃,不甜!" << std::endl;
	}
	EgyptWatermelon() {
		std::cout << "埃及西瓜的构造函数被调用!" << std::endl;
	}
	~EgyptWatermelon() {
		std::cout << "埃及西瓜的析构函数被调用!" << std::endl;
	}
};
//具体产品:埃及橙子
class EgyptOrange :public AbstrctOrange {
public:
	virtual void Orange()
	{
		std::cout << "埃及橙子不好吃,不甜!" << std::endl;
	}
	EgyptOrange() {
		std::cout << "埃及橙子的构造函数被调用!" << std::endl;
	}
	~EgyptOrange() {
		std::cout << "埃及橙子的析构函数被调用!" << std::endl;
	}
};

3、创建抽象工厂

抽象工厂声明了一组用于创建产品对象的方法,每个方法对应一种产品类型,

//抽象工厂
class AbstrctFactory {
public:
	virtual AbstrctWatermelon* createWatermelon() = 0;
	virtual AbstrctOrange* createOrange() = 0;
	AbstrctFactory() {
		std::cout << "抽象工厂的构造函数被调用!" << std::endl;
	}
	~AbstrctFactory() {
		std::cout << "抽象工厂的析构函数被调用!" << std::endl;
	}
};

4、创建具体工厂

实现了抽象工厂接口,负责创建具体产品对象的实例

//具体工厂:中国工厂
class ChinaFactory :public AbstrctFactory {
public:
	virtual AbstrctWatermelon* createWatermelon() {
		return new ChinaWatermelon;
	}
	virtual AbstrctOrange* createOrange() {
		return new ChinaOrange;
	}
	ChinaFactory() {
		std::cout << "中国工厂的构造函数被调用!" << std::endl;
	}
	~ChinaFactory() {
		std::cout << "中国工厂的构造函数被调用!" << std::endl;
	}
};
//具体工厂:埃及工厂
class EgyptFactory :public AbstrctFactory {
public:
	virtual AbstrctWatermelon* createWatermelon() {
		return new EgyptWatermelon;
	}
	virtual AbstrctOrange* createOrange() {
		return new EgyptOrange;
	}
	EgyptFactory() {
		std::cout << "埃及工厂的构造函数被调用!" << std::endl;
	}
	~EgyptFactory() {
		std::cout << "埃及工厂的构造函数被调用!" << std::endl;
	}
};

5、调用

通过创建抽象工厂与具体工厂的对象,并使用这些工厂对象来创建相应的产品对象。通过产品对象调用其特定的函数来完成相应的步骤。

在调用完成后,因为创建了三个指针,所以要将其释放,并置为空。

int main()
{
	AbstrctFactory* abf = new ChinaFactory;
	AbstrctWatermelon* cwatermelon = abf->createWatermelon();
	AbstrctOrange* cOrange = abf->createOrange();
	cwatermelon->Watermelon();
	cOrange->Orange();

	delete cOrange; cOrange = nullptr;
	delete cwatermelon; cwatermelon = nullptr;
	delete abf; abf = nullptr;
}

6、代码执行


四、优缺

优点

当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。

缺点

产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象部分添加加代码,又要在具体部分加代码。


五、应用场景

  • 客户端(应用层)不依赖与产品类示例如何被创建、实现等细节
  • 强调一系列相关的产品对象(数据同一产品族)一起使用创建对象需要大量的重复代码
  • 提供一个产品类的库,所有的产品以同样的接口出现,使得客户端不依赖于具体实现

例如

  • QQ 换皮肤,一整套一起换
  • 生成不同操作系统的程序
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值