抽象工厂(Abstruct Factory)模式

抽象工厂(Abstruct Factory)模式

之前一直强调,工厂模式只能为一类类提供对象的创建。而抽象工厂模式与之最大区别,便是它能为多个有依赖关系的类实现对象的创建。

我更倾向于认为,当在工厂模式中有多个不相同的基类,但其特征在实例化的类上产生了交叉。我们将这些不同的特征在产品类族与工厂类族中用相反的继承关系表达出来,完成对一类相关类的创建。

举个例子: 在一款游戏中,用户使用的道具(Prop)分为武器(Weapon)和玩具(Toy),枪械(Gun)有手枪(Handgun)和猎枪(Shotgun)。道具实体有武器手枪(WeaponHandgun),武器猎枪(WeaponShotgun),玩具手枪(ToyHandgun),玩具猎枪(ToyShotgun).很明显,道具特征和枪械特征在其共同的派生类中完成了整合。(由于某些语言不支持多重继承,也就不使用多重继承)也就是这两个类具有相关性。

image

如图: FactoryGun提供的是两类(Weapon,Toy)对象的创建,而具体创建那种实例,需要其派生类来决定。我们发现,在产品类族中,道具,与枪械类型的继承关系与工厂类族正好相反,产品类族中,枪械类型是从道具中分化出来,而在工厂类族中,我们枪械类型决定具体的产品。也就是说,在产品类族中,我们首先确定是哪种道具,然后在确定是哪种枪械;在工厂类族中,我们在知道枪械类型后,通过调用函数的不同,才确定是那种道具。这样,当我们需要增加枪械类型时,直接更改工厂的派生类型;当增加了道具类型时,更改基类类型。

***注意:***,此UML图中体现上面所说的特征逆置不太直观,可以尝试着去掉FactoryGun,按照工厂方法写出来,就会比较直观的看到多个类,及依赖关系在产品类族中与在工厂类族中的不同。

其实,这种逆置是符合依赖倒置原则的。

//weapon.hpp

#include <iostream>
#ifndef _DESIGN_PATTERN_ABSTRACT_FACTORY_WEAPON_HPP_
#define _DESIGN_PATTERN_ABSTRACT_FACTORY_WEAPON_HPP_

namespace design_pattern
{

class Weapon
{
public:
	virtual ~Weapon() {}
	virtual void Shoot() = 0;
};

class WeaponHandgun : public Weapon
{
public:
	void Shoot()
	{
		std::cout << "WeaponHandgun shoot: 10.0" << std::endl;
	}
};

class WeaponShotgun : public Weapon
{
public:
	void Shoot()
	{
		std::cout << "WeaponShotgun shoot: kill a goat" << std::endl;
	}
};

}

#endif //!_DESIGN_PATTERN_ABSTRACT_FACTORY_WEAPON_HPP_

//toy.hpp

#include <iostream>

#ifndef _DESIGN_PATTERN_ABSTRACT_FACTORY_TOY_HPP_
#define _DESIGN_PATTERN_ABSTRACT_FACTORY_TOY_HPP_

namespace design_pattern
{
class Toy
{
public:
	virtual ~Toy() {}
	virtual void Shoot() = 0;
};

class ToyHandgun : public Toy
{
public:
	void Shoot()
	{
		std::cout << "ToyHandgun shoot: bi bi bu..." << std::endl;
	}
};

class ToyShotgun : public Toy
{
	void Shoot()
	{
		std::cout << "ToyShotgun shoot: so so so..." << std::endl;
	}
};
}
#endif // !_DESIGN_PATTERN_ABSTRACT_FACTORY_TOY_HPP_

//factory_gun.hpp

#include "weapon.hpp"
#include "toy.hpp"

#ifndef _DESIGN_PATTERN_ABSTRACT_FACTORY_FACTORY_GUN_HPP_
#define _DESIGN_PATTERN_ABSTRACT_FACTORY_FACTORY_GUN_HPP_

namespace design_pattern
{

class FactoryGun
{
public:
	virtual ~FactoryGun() {}

	virtual Weapon* CreateWeapon() = 0;
	virtual Toy*  CreateToy() = 0;
};

class FactoryHandgun : public FactoryGun
{
public:
	Weapon* CreateWeapon()
	{
		return new WeaponHandgun;
	}

	Toy* CreateToy()
	{
		return new ToyHandgun;
	}

};
class FactoryShotgun : public FactoryGun
{
	Weapon* CreateWeapon()
	{
		return new WeaponShotgun;
	}

	Toy* CreateToy()
	{
		return new ToyShotgun;
	}
};
}
#endif // !_DESIGN_PATTERN_ABSTRACT_FACTORY_FACTORY_GUN_HPP_

//abstract_factory_main.cpp

#include "weapon.hpp"
#include "toy.hpp"
#include "factory_gun.hpp"
using namespace design_pattern;

int main()
{
	FactoryGun *phand = new FactoryHandgun;
	FactoryGun *pshot = new FactoryShotgun;

	Weapon *pwhg = phand->CreateWeapon();
	Toy *pthg = phand->CreateToy();

	Weapon *pwsg = pshot->CreateWeapon();
	Toy *ptsg = pshot->CreateToy();

	pwhg->Shoot();
	pwsg->Shoot();
	pthg->Shoot();
	ptsg->Shoot();

	return 0;
}
语法tips
  • C++继承之内存布局
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值