《设计模式》:简单工厂、工厂方法及抽象工厂

简单工厂工厂方法都集中封装了对象的创建过程,使得要更改对象时,不需做大的改动就能实现,降低了客户程序与产品对象的耦合。

//不使用工厂进行对象创建
class Computer
{
	public:
		virtual void show() = 0;
};

class DellComputer : public Computer
{
	public:
		void show()
		{
			std::cout << "This is Dell computer!" << endl;
		}
};


class HaseeComputer: public Computer
{
	public:
		void show()
		{
			std::cout << "This is Haseecomputer!" << endl;
		}
};


int main()
{
	Computer *pComputer = NULL;
	if(客户端需要HaseeComputer)
		pComputer  = new HaseeComputer;
	else if(客户端需要DellComputer)
		pComputer  = new DellComputer;
	else
		......			//当有其他电脑品牌的类时就需要修改main函数中的代码,违背了对扩展开放,对修改关闭的原则
	pComputer->show();
	return 0;
}

使用简单工厂,增加新类SimpleFactory

class SimpleFactory
{
	public:
		Computer *CreateComputer(string computer)
		{
			if(computer == "HaseeComputer")
				pComputer  = new HaseeComputer;
			else if(computer == "DellComputer")
				pComputer  = new DellComputer;
			else
				......			//当有其他电脑品牌的类时就需要修改main函数中的代码,违背了对扩展开放,对修改关闭的原则
			
		}
}

使用简单工厂后,main函数则改为

int main()
{
	SimpleFactory *pFactory = new SimpleFactory;
	pFactory->CreateComputer("HaseeComuter");
	return 0;
}

可以看出,使用简单工厂后的main函数,不需要执行具体对象创建的细节,也就是无需在主函数中做判断,取而代之的是定义一个简单工厂的类,并通过工厂类中的CreateComputer函数返回一个对象,对象的类型通过传参的方式进入函数中。这样在调用者中只需要对参数进行修改即可实现不同对象的创建,减少了代码修改程度。
但反观简单工厂类class SimpleFactory可知,简单工厂与普通的创建对象方法的区别就是他把之前在main函数中的判断过程移到了简单工厂中实现。这样虽然可以减少客户端的代码量,但是如果有新的电脑型号出现时,就需要更改SimpleFactory类的内容,增加新的判断,破坏了对修改关闭的原则。
为了解决上述问题,引入工厂方法
使用工厂方法解决上述问题,需要引入新的类。

class ComputerFactory	//这个类相当于简单工厂类SimpleFactory,只不过将简单工厂中的实现延迟到了子类
{						//只把实现的接口定义出来
	virtual Computer *CreateComputer() = 0;		//定义为纯虚函数,在子类对该函数进行实现。
};

class DellComputerFactory
{
	Computer *CreateComputer()
	{
		return new DellComputer;
	}
};

class HaseeComputerFactory
{
	Computer *CreateComputer()
	{
		return new HaseeComputer;
	}
};

这时主函数的写法如下

int main()
{
	ComputerFactory *pFactory = new HaseeComputerFactory;		//根据需要定义对应工厂
	Computer *pComputer = pFactory->CreateComputer();
	pComputer->show();											//显示This is Haseecomputer!
	return 0;
}

注意到此时如果需要添加新的电脑品牌,至于要添加一个对应的产品类和相应的产品工厂类即可,而无需对现有的类进行修改,实现了对拓展的开放对修改的关闭

抽象工厂模式

现在考虑这样一个问题,Dell和Hasee两个厂商不可能只有电脑这一种类型的产品,假如现在增加了一个产品类型显示器,则需要增加一个抽象类Monitor和两个子类DellMonitor和HaseeMonitor。

class Monitor
{
	public :
		virtual void show() = 0;
};

class DellMontor : public Monitor
{
	public:
		void show()
		{
			std::cout << "This is a Dell Monitor" << endl;
		}
};

class HaseeMontor : public Monitor
{
	public:
		void show()
		{
			std::cout << "This is a Hasee Monitor" << endl;
		}
};

增加产品类之后,可将工厂方法中的三个工厂改为如下形式

class Factory
{
	virtual Computer *CreateComputer() = 0;		
	virtual Monitor *CreateMonitor() = 0;
};

class DellComputerFactory
{
	Computer *CreateComputer()
	{
		return new DellComputer;
	}
	Monitor *CreateMonitor()
	{
		return new DellMontor;
	}
};

class HaseeComputerFactory
{
	Computer *CreateComputer()
	{
		return new HaseeComputer;
	}
	Monitor *CreateMonitor()
	{
		return new HaseeMontor;
	}
	
};

这样一个抽象工厂就产生了。类Factory作为抽象工厂的接口类,其子类产生具体的实例化对象。
通过上面三个类的定义可以发现,抽象工厂中每一个产品的创建过程都是一个工厂方法
Computer和Monitor构成一个产品族。在抽象工厂中,一个实例化的工厂可以创建一个完整的产品族,产品族中的每个产品出于不同的产品结构
产品等级结构:即产品的继承结构。例如Computer类和他的子类DellComputer及HaseeComputer构成了一个产品等级结构。而Computer和Monitor自然出于不同的产品等级结构。
产品族:处于不同产品等级结构的一族产品的合集。

这时在主函数中可以这样实现

int main()
{
	Factory *pFactory = new DellFactory;		//假设创建一个Dell系列产品
	Computer *pComputer = pFactory->CreateComputer();
	Monitor *pMonitor = pFactory->CreateMonitor();
	pComputer->show();			//This is DellComputer!
	pMonitor ->show();			//This is DellMonitor!
	return 0;
}

从客户端代码可以看出,抽象工厂的好处是对同一产品族的产品进行了统一的设计。这里体现为对Dell厂商的产品进行了封闭的设计,保证了产品族中产品的统一。

如果在产品中新增一个继承父类的子类厂商Mac,那么需要增加一个MacFactory来创建MacComputer和MacMonitor。

抽象工厂也存在一定的缺点

当添加一个产品时,需要修改很多代码。在上个例子中,如果增加一个产品为Mouse,那么在增加新产品的同时还需要更改Factory及其子类的内容,增加CreateMouse的工厂方法。

从上面的分析可以看出:(1)增加一个产品的继承结构如Mac只需要增加新的MacFactory并对其实现即可,属于结构拓展。
(2)但如果增加一个新的产品如Mouse,则需要对现有的工厂进行修改,这破坏了开闭原则,这也是抽象工厂的缺点所在。

针对抽象工厂的缺点进行如下改进。

用简单工厂优化抽象工厂(解决扩展产品的灵活度不足的问题)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值