C++设计模式之抽象工厂模式(二)

3、抽象工厂模式概述

    抽象工厂模式为创建一组对象提供了一种解决方案。与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品。抽象工厂模式定义如下:

    抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。它是一种对象创建型模式。

    在抽象工厂模式中,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品,这些产品可以没有任何的联系,且位于不同的产品等级中,但这些产品可以组合起来,构成了一个产品族。

抽象工厂模式结构图

    在抽象工厂模式结构图中包含如下几个角色:

    AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的工厂方法,每一个工厂方法对应一种产品。这些产品可以没有任何的联系,但这些产品可以组合起来,可以构成一个产品族。

    ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的工厂方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。

    AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。

    ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。


4、使用抽象工厂实现BeyongdCompare



代码格式类型图


格式工厂图

    要在Windows和Linux平台下都能对Cpp和Java代码格式文件进行比较,考虑到扩展性,可以定义一个抽象CPP类,Windows平台下的Cpp格式和Linux平台下的Cpp格式都继承于这个抽象Cpp类。 同时定义一个抽象Java类,Windows平台下的Java格式和Linux平台下的Java格式都继承于这个抽象Java类。
    定义一个抽象格式工厂,Windows格式工厂继承于抽象格式工厂,用于创建Windows下的Cpp和Java格式对象。 Linux格式工厂也继承于抽象格式工厂,用于创建Linux下的Cpp和Java格式对象。
    代码格式类型实现如下:
#ifndef _PRODUCT_H_
#define _PRODUCT_H_
#include <iostream>
#include <string>
using namespace std;

//抽象Cpp代码格式类
class CppCodeStyle
{
public:
	//虚函数,用于显示处理的代码格式
	virtual void DisplayCodeStyle() = 0;
};


//Windows Cpp代码格式
class WindowsCppCodeStyle : public CppCodeStyle
{
public:
	void DisplayCodeStyle()
	{
		cout << "我对Windows Cpp文件进行代码比较" << endl;
	}
};


//Linux Cpp代码格式
class LinuxCppCodeStyle : public CppCodeStyle
{
public:
	void DisplayCodeStyle()
	{
		cout << "我对Linux Cpp文件进行代码比较" << endl;
	}
};

/*********************************************************/
/*********************************************************/

//抽象Java代码格式
class JavaCodeStyle
{
public:
	//虚函数,用于显示处理的代码格式
	virtual void DisplayCodeStyle() = 0;
};


//Windows Java代码格式
class WindowsJavaCodeStyle : public JavaCodeStyle
{
public:
	void DisplayCodeStyle()
	{
		cout << "我对Windows Java文件进行代码比较" << endl;
	}
};


//Linux Java代码格式
class LinuxJavaCodeStyle : public JavaCodeStyle
{
public:
	void DisplayCodeStyle()
	{
		cout << "我对Linux Java文件进行代码比较" << endl;
	}
};

#endif
    BeyondCompare软件能运行在Windows平台和Linux平台,每个平台都能对Cpp文件和Java文件进行比较。因此可以创建一个Windows工厂,用于创建Windows下的Cpp对象和Java对象。创建一个Linux工厂,用于创建Linux下的Cpp对象和Java对象。这样Cpp对象和Java对象就被限制在了某个平台下。即Cpp对象和Java对象要么同属于Windows,要么同属于Linux。而不会出现使用简单工厂模式出现的情况:"Cpp属于Windows平台,而Java属于Linux平台"。
    格式工厂实现代码如下:
#ifndef _PRODUCT_FACTORY_H_
#define _PRODUCT_FACTORY_H_
#include "Product.h"

//抽象代码格式工厂
class CodeStyleFactory
{
public:
	//工厂方法,创建具体的Cpp格式对象
	virtual CppCodeStyle * CreateCpp() = 0;

	//工厂方法,创建具体的Java格式对象
	virtual JavaCodeStyle * CreateJava() = 0;
};


//Windows代码格式工厂
class WindowsCodeStyleFactory : public CodeStyleFactory
{
public:
	//工厂方法,创建具体的Cpp格式对象
	CppCodeStyle * CreateCpp()
	{
		CppCodeStyle * pCppCodeStyle = new WindowsCppCodeStyle();

		return pCppCodeStyle;
	}

	//工厂方法,创建具体的Java格式对象
	JavaCodeStyle * CreateJava()
	{
		JavaCodeStyle * pJavaCodeStyle = new WindowsJavaCodeStyle();

		return pJavaCodeStyle;
	}
};


//Linux代码格式工厂
class LinuxCodeStyleFactory : public CodeStyleFactory
{
public:
	//工厂方法,创建具体的Cpp格式对象
	CppCodeStyle * CreateCpp()
	{
		CppCodeStyle * pCppCodeStyle = new LinuxCppCodeStyle();

		return pCppCodeStyle;
	}

	//工厂方法,创建具体的Java格式对象
	JavaCodeStyle * CreateJava()
	{
		JavaCodeStyle * pJavaCodeStyle = new LinuxJavaCodeStyle();
		
		return pJavaCodeStyle;
	}
};

#endif
    测试文件实现代码如下:
#include <iostream>
using namespace std;
#include "Product.h"
#include "ProductFactory.h"

int main()
{
	/*************创建Windows Cpp ************************************/
	CodeStyleFactory * pWindowsCodeStyleFactory = new WindowsCodeStyleFactory();
	CppCodeStyle * pWindowsCppCodeStyle = pWindowsCodeStyleFactory->CreateCpp();
	pWindowsCppCodeStyle->DisplayCodeStyle();

	/*************创建Windows Java ************************************/
	JavaCodeStyle * pWindowsJavaCodeStyle = pWindowsCodeStyleFactory->CreateJava();
	pWindowsJavaCodeStyle->DisplayCodeStyle();
	
	cout << "***********************************" << endl;

	/*************创建Linux Cpp ************************************/
	CodeStyleFactory * pLinuxCodeStyleFactory = new LinuxCodeStyleFactory();
	CppCodeStyle * pLinuxCppCodeStyle = pLinuxCodeStyleFactory->CreateCpp();
	pLinuxCppCodeStyle->DisplayCodeStyle();
	
	/*************创建Linux Java ************************************/
	JavaCodeStyle * pLinuxJavaCodeStyle = pLinuxCodeStyleFactory->CreateJava();
	pLinuxJavaCodeStyle->DisplayCodeStyle();

	/*************销毁Windows相关对象操作****************************/
	delete pWindowsCodeStyleFactory;
	pWindowsCodeStyleFactory = NULL;
	delete pWindowsCppCodeStyle;
	pWindowsCppCodeStyle = NULL;
	delete pWindowsJavaCodeStyle;
	pWindowsJavaCodeStyle = NULL;

	/*************销毁Linux相关对象操作****************************/
	delete pLinuxCodeStyleFactory;
	pLinuxCodeStyleFactory = NULL;
	delete pLinuxCppCodeStyle;
	pLinuxCppCodeStyle = NULL;
	delete pLinuxJavaCodeStyle;
	pLinuxJavaCodeStyle = NULL;

	return 0;
}
    编译并执行,程序结果如下:


5、抽象工厂模式总结

       简单工厂模式和工厂方法模式都只产生一种类型的产品对象。然而在抽象工厂模式中,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品,这些产品可以没有任何的联系,位于不同的产品等级,但这些产品可以组合起来,构成一个产品族。抽象工厂模式是工厂方法模式的进一步延伸,由于它提供了功能更为强大的工厂类并且具备较好的可扩展性,在软件开发中得以广泛应用。使用抽象工厂模式来实现在不同的操作系统中应用程序呈现与所在操作系统一致的外观界面。

1.主要优点

    抽象工厂模式的主要优点如下:

    (1) 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易,所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。抽象工厂封装了变化,封装了对象创建的具体细节,对客户端隐藏对象创建的具体细节,符合"封装变化原则"。

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

    (3) 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。

    (4) 客户端可以针对抽象进行编程,而不需要知道具体类型,符合"针对接口进行编程而不是针对具体进行编程原则"。

2.主要缺点

    抽象工厂模式的主要缺点如下:

    增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则"

3、抽象工厂模式具体应用

    (1)根据项目的需要,可以使用Sqlserver、Access、Mysql等数据库存储一些对象。例如用任意一种数据库存储部门表、员工表。这是抽象工厂模式的一种应用,可以随时切换数据库进行存储。

    (2)QQ空间背景样式,博客背景样式等都提供了各种风格的样式。在Windows平台和Linux平台下会有不同的显示方式。

    (3)开发一个可以在Windows、Linux、Android平台下运行的图片阅读器,不同平台下有不同的显示方式。

    (4)网页下载工具的开发: 根据需要可以下载新浪网页、腾讯网页、搜狐网页等。而在不同平台下,下载方式可能会不相同。

    (5)淘宝购物最后一个支付环节,可以选择货到付款、网上银行、支付宝等类型支付。在不同平台上,各种支付的方式可能在操作上存在些差异。

    (6)开发一款可以运行在Windows和Andorid平台的射击游戏,Windows下有手枪、AK47、步枪、大刀等武器,Linux同样也存在这些武器。

    (7)开发火车票图像识别软件(OCR),可以在Windows平台和Linux平台运行。对识别的结果可以保存为txt、word、pdf等格式。

    (8)STL里面的集合容器List、Vector、Deque等,不管使用哪种类型的容器,都可以使用迭代进行抽象操作。 

    (9)生活中也有很多类似的工厂: 伟创力各个生产车间生产不同的产品; 生产海尔冰箱、海尔空调这些产品;肯德基麦当劳在全球设置各个分工厂;中国石油、紫金矿业、景德镇陶瓷、中国移动、伊利蒙牛在全国的各个分工厂;顺丰快递、申通快递在全国的驿站等。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值