抽象工厂模式

例子是大话设计模式上第15章的内容,用抽象工厂模式,实现了程序中业务逻辑与数据访问的解耦。

抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。侧重点:多个系列的话可以考虑。

适用性:

1 一个系统要独立于它的产品创建,组合与表示时

2 一个系统要由多个产品系列中的一个来配置时

3 当要情调一系列相关的产品对象的设计以便进行联合使用时。

4 当提供一个产品类库,而只想显示它们的接口而不是实现时

结构图:

      与工厂方法的区别是,工厂方法只是一个抽象工厂类,并不对商品进行系列划分,这些上面是一样的关系,而抽象工厂,将商品分为不同系列的,而针对不同的系列对应有不同的工厂,一个系列对应一个工厂。

参与者:

       AbstractorFactory:声明一个抽象产品对象的操作接口(定义了所有种类商品的创建接口)

      ConcreteFactory:实现创建具体产品对象的操作(一个工厂对应这个系列的所有的商品的创建)

      AbstractProduct: 为一类产品对象声明一个接口

      ConcreteProduct:定义一个将被相应的具体工厂创建的产品对象,实现abstractProduct的接口

     Client: 仅使用由AbstractFactory和AbstractProduct类声明的接口。

协作:

     通常在运行时刻创建一个ConcreteFactory的实例,这一个具体的工厂创建具有特定实现的产品对象。为创建不同的产品对象,客户可以还具体工厂就可以实现了。

      AbstractFactory将产品对象的创建延迟到它的ConcreteFactory的子类中

效果:

(1)分离了具体的类,工厂将客户与商品类的实现分离,客户不需要知道具体类的类名,只需要调用工厂中的接口

(2)易于交换产品系列,更改产品系列只需要更改一个具体工厂类的初始化。

(3)有利于产品的一致性:因为一系列的产品被设计到一个工厂中

(4)缺点阿,难以支持新种类的产品,因为抽象共存接口确定了可以被创建的产品集合,而添加一个新种类就要增加新的商品子类,然后队抽象工厂和具体工厂都需要更改。

实现:

(1)将工厂实现为单件模式:一个产品系列只需一个具体工厂的实例。

(2)创建产品:工厂方法模式是对每一个商品定义一个工厂方法。抽象工厂是要求队每个产品系列都要有一个新的工厂子类,即使差别很小。

(3)定义可扩展的工厂:改进它的缺点。

以下是书上问题的代码实现:

//抽象工厂模式,提供一个创建一系列相关或相互依赖对象的接口,
//而无需指定他们的类。如SqlserverFactory提供创建Sqlserver相关的用户和部门
//优点:易于交换系列产品。具体的常见实例过程与客户端分离,
//缺点:增加一个表后,需要更改三个工厂类
#include <iostream>
#include <string>
using namespace std;

//User类,User表中的数据,供插入查询操作
class User
{
public:
    int GetId()
	{
		return id;
	}

	string GetName()
	{
		return name;
	}

	void SetId(int _id)
	{
		id = _id;
	}

	void SetName(string _name)
	{
		name = _name;
	}

private:
	int id;
	string name;
};

//User表的接口,有插入和查询操作
class IUser
{
public:
	virtual void Insert(User &user)
	{

	}

	virtual User* GetUser(int id)
	{
		return NULL;
	}
};

//SqlserverUser表
class SqlserverUser : public IUser
{
public:
    void Insert(User &user)
	{
		cout << "在SQL Server中给User表增加一条记录" << endl;
	}

	User* GetUser(int id)
	{
        cout << "在SQL Server中根据ID得到User表一条记录" << endl;
		return NULL;
	}
};

//AccessUser表
class AccessUser : public IUser
{
public:
	void Insert(User &user)
	{
		cout << "在Access中给User表增加一条记录" << endl;
	}

	User* GetUser(int id)
	{
		cout << "在Access中根据ID得到User表一条记录" << endl;
		return NULL;
	}
};

//Department类,为Department插入数据
class Department
{
public:
	int GetId()
	{
		return id;
	}

	string GetName()
	{
		return deptname;
	}

	void SetId(int _id)
	{
		id = _id;
	}

	void SetName(string _deptname)
	{
		deptname = _deptname;
	}

private:
	int id;
	string deptname;
};

//IDpartment表的接口,又插入和查询操作
class IDepartment
{
public:
	virtual void Insert(Department &dept)
	{

	}

	virtual Department* GetDepartment(int id)
	{
        return NULL;
	}
};

//SqlserverDepartment表
class SqlserverDepartment : public IDepartment
{
public:
	void Insert(Department &dept)
	{
		cout << "在SQL Server中给Department表增加一条记录" << endl;
	}

	Department* GetDepartment(int id)
	{
		cout << "在SQL Server中根据ID得到Department表一条记录" << endl;
		return NULL;
	}
};

//AccessDepartment表
class AccessDepartment : public IDepartment
{
public:
	void Insert(Department &dept)
	{
		cout << "在Access中给Department表增加一条记录" << endl;
	}

	Department* GetDepartment(int id)
	{
		cout << "在Access中根据ID得到Department表一条记录" << endl;
		return NULL;
	}
};

//工厂类,用于产生数据库中的各种表
class IFactory
{
public:
	virtual IUser* CreateUser()
	{
        return NULL;
	}

	virtual IDepartment* CreateDepartment()
	{
		return NULL;
	}
};

//用于产生使用SqlServer数据库中的user表与department表
class SqlserverFactory : public IFactory
{
public:
	IUser* CreateUser()
	{
		return new SqlserverUser;
	}

	IDepartment* CreateDepartment()
	{
		return new SqlserverDepartment;
	}
};

//用于产生使用Access数据库中的user表与department表
class AccessFactory : public IFactory
{
public:
	IUser* CreateUser()
	{
		return new AccessUser;
	}

	IDepartment* CreateDepartment()
	{
		return new AccessDepartment;
	}
};

int main()
{
	//供插入数据使用
	User user;
	Department dept;

	//如果要更改数据库,只需要更改这一句new SqlserverFactory
	IFactory *factory = new AccessFactory();
	//只知道创建了User,但是不知道创建的是什么User
	IUser *iuser = factory->CreateUser();
	iuser->Insert(user);
	iuser->GetUser(1);

	IDepartment* idept = factory->CreateDepartment();
	idept->Insert(dept);
	idept->GetDepartment(1);

	system("pause");
	return 0;
	
}

最大的好处是易于交换产品系列,由于具体工厂类,如IFactory  factory = new AccessFactory(),在一个应用中只需要在初始化的时候出现一次,就可以改变一个应用的具体工厂变得非常容易,只需要改变具体工厂即可使用不同的产品配置。

第二个好处是:让具体的创建实例过程与客户端分离,客户端是通过它们你的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户端代码中,这就解决了工厂模式的需要修改客户端的问题。

但是模式都有缺点,这个针对这个问题,当需要增加一个项目表Project,则需要增加三个类,IProject,SqlserverProject, AccessProject,还需要更改IFactory,SqlserverFactory,AccessFactory才能实现。。。


GoF书上Maze例子的UML图:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值