简单工厂模式,工厂模式

今天看了一下工厂相关的模式,一个思想就是将对象的创建都放在工厂里,工厂负责生产对象。工厂屏蔽了具体构造了什么对象。

相关的模式有三种:简单工厂模式,工厂模式,抽象工厂模式。

第一种:简单工厂模式

将创建对象的逻辑放在工厂里,以书上计算器的代码为例,以下为简单工厂模式的实现,代码中有相关的解释

//简单工厂模式实现的计算器,
//1 有一个运算的基类,各类运算继承该基类,如果增加新的运算,则只增加子类,不用再更改别的类
//2 一个factory实现实例的创建,在工厂里生产运算类,决定到底使用哪个运算类,不用在客户端进行判断
//优点:将逻辑判断归纳入工厂类,客户端不用管理,
//缺点:增加新的运算后,都要更改工厂类,违反了开放封闭原则(类本身不应修改,开放扩展接口)。
#include <iostream>
using namespace std;

class Operation
{
public:
	Operation() : _numberA(0), _numberB(0)
	{

	}

	Operation(double numberA, double numberB)
		: _numberA(numberA), _numberB(numberB)
	{

	}

	//别的类通过这两个函数访问私有变量
	double GetNumberA()
	{
		return _numberA;
	}

	double GetNumberB()
	{
		return _numberB;
	}

	//设置私有变量的值
	void SetNumberA(double numberA)
	{
        _numberA = numberA;
	}

	void SetNumberB(double numberB)
	{
		_numberB = numberB;
	}

	//继承类继承的接口
    virtual double GetResult() 
	{
        double result = 0.0;
		return result;
	}
private:
	double _numberA;
	double _numberB;
};

//继承类不能访问基类的私有成员
class OperationAdd : public Operation
{
public:
	double GetResult()
	{
		return GetNumberA() + GetNumberB();
	}
};

class OperationSub : public Operation
{
public:
	double GetResult()
	{
		return GetNumberA() - GetNumberB();
	}
};

class OperationMul : public Operation
{
public:
	double GetResult()
	{
		return GetNumberA() * GetNumberB();
	}
};

class OperationDiv : public Operation
{
public:
	double GetResult()
	{
		//抛出异常
		if (GetNumberB() == 0)
		   throw exception("除数不能为0");
		return GetNumberA() / GetNumberB();
	}
};

//工场函数,用于构造实例
class OperationFactory
{
public:
	//定义为static类是为了可以使用类名直接访问该函数,
	//不用另外定义该类的对象然后访问函数
	static Operation* createFactory(char op)
	{
		//定义一个基类对象的指针,动态决定运行
		//时指向哪一个继承类对象,运用了多态。
		Operation *oper = NULL;
		switch (op)
		{
		case '+':
			oper = new OperationAdd;
			break;
		case'-':
			oper = new OperationSub;
		case '*':
			oper = new OperationMul;
			break;
		case '/':
			oper = new OperationDiv;
			break;
		}
		return oper;
	}
};

int main()
{
	Operation *poper = NULL;	
	//创建一个工厂用于产生对象。
    poper = OperationFactory::createFactory('+');
	poper->SetNumberA(4);
	poper->SetNumberB(9);
	cout << poper->GetResult() << endl;
	
	system("pause");
	return 0;
}

简单工厂模式最大优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。

缺点是如上面的例子,当我又增加一个新的计算功能,求M的N次方,首先增加一个运算的子类,然后要修改原来的工厂类,加一个swtich case语句,但这违背了开放封闭原则,并不是扩展,而是修改原来的类,所以下面的工厂模式就克服了这个缺点。

第二种:. 工厂模式 

定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。

工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在,即工厂方法把简单工厂的内部逻辑判断移到了客户端代码进行。如果要加功能,本来是改工厂类的,现在是修改客户端。

 适用性:

1 当一个类不知道它所必须创建的对象的类的时候

2 当一个类希望由它的子类来指定它所创建的对象的时候

3 当类将创建对象的职责委托给多个帮助子类中的一个,你希望将哪一个帮助子类是代理这这一信息局部化的时候。

结构图:

参与者:

Product:定义工厂方法所创建爱你的对象的接口

ConcreteProduct :实现product的接口

Creator:声明工厂方法,该方法返回一个product对象。Creator可以定义一个工厂方法的缺省实现,返回一个缺省的ConcreteProduct对象。可以调用工厂方法创建一个Product对象。

ConcreteCreator:重定义共存方法以返回一个ConcreteProduct实例。

协作:

Creator依赖于它的子类来定义工厂方法,所以返回一个适当的ConcreteProduct实例。

效果:

不再将应用有关的类绑定到代码中,代码仅处理Product接口,不用与ConcreteProduct打叫道。但一个潜在的缺点是客户创建了一个具体的子类,就得在增加一个工厂的子类。

实现:

1 主要有两种情况:一种是Creator类是一个抽象类而且不提供所声明的工厂方法的实现,一种是Creator是一个具体的类而且为共存方法提供一个缺省的实现,也可能有一个定义了缺省实现的抽象类,但是不太常见。

2 参数化共存,

4 关于子类创建问题,C++中可以用模板来避免创建子类,将Producr作为模板参数传给StandordCreator,这样避免了子类创建,模板真好。

以下是计算器类的工厂方法实现:

//工厂模式实现的计算器,
//1 有一个运算的基类,各类运算继承该基类,如果增加新的运算,则只增加子类,不用再更改别的类
//2 一个工厂的基类,各个工厂继承该基类,如果增加新的运算,则不用再更改工厂类,而只是添加新的继承类
//优点:解决了简单工厂模式要修改工厂类的问题,即改正了开放封闭原则,
//缺点:增加新的运算后,需要更改客户端的代码,将判断由工厂类移到了客户端
#include <iostream>
using namespace std;

class Operation
{
public:
	Operation() : _numberA(0), _numberB(0)
	{

	}

	Operation(double numberA, double numberB)
		: _numberA(numberA), _numberB(numberB)
	{

	}

	//别的类通过这两个函数访问私有变量
	double GetNumberA()
	{
		return _numberA;
	}

	double GetNumberB()
	{
		return _numberB;
	}

	//设置私有变量的值
	void SetNumberA(double numberA)
	{
		_numberA = numberA;
	}

	void SetNumberB(double numberB)
	{
		_numberB = numberB;
	}

	//继承类继承的接口
	virtual double GetResult() 
	{
		double result = 0.0;
		return result;
	}
private:
	double _numberA;
	double _numberB;
};

//继承类不能访问基类的私有成员
class OperationAdd : public Operation
{
public:
	double GetResult()
	{
		return GetNumberA() + GetNumberB();
	}
};

class OperationSub : public Operation
{
public:
	double GetResult()
	{
		return GetNumberA() - GetNumberB();
	}
};

class OperationMul : public Operation
{
public:
	double GetResult()
	{
		return GetNumberA() * GetNumberB();
	}
};

class OperationDiv : public Operation
{
public:
	double GetResult()
	{
		//抛出异常
		if (GetNumberB() == 0)
			throw exception("除数不能为0");
		return GetNumberA() / GetNumberB();
	}
};

//工厂函数的基类,其他工厂用于继承
class OperationFactory
{
public:
    virtual Operation *CreateOperation()
	{
        return NULL;
	}
};

class AddFactory : public OperationFactory
{
public:
	Operation* CreateOperation()
	{
		return new OperationAdd;
	}
};

class SubFactory : public OperationFactory
{
public:
	Operation* CreateOperation()
	{
		return new OperationSub;
	}
};

class MulFactory : public OperationFactory
{
public:
	Operation* CreateOperation()
	{
		return new OperationMul;
	}
};

class DivFactory : public OperationFactory
{
public:
	Operation* CreateOperation()
	{
		return new OperationDiv;
	}
};

int main()
{
	Operation *poper = NULL;
	//需要更改这里的代码
	OperationFactory *operf = new DivFactory;
	poper = operf->CreateOperation();
	poper->SetNumberA(27);
	poper->SetNumberB(9);
	cout << poper->GetResult() << endl;

	system("pause");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值