工厂(Factory)模式

工厂模式

工厂模式一般分为三种:

其中简单工厂与工厂方法在GoF中统称为工厂模式。由于所有创建型模式都的基本要求就是为对象的创建提供接口,封装对象的生成。所以简单工厂不专门作为一种创建型模式。但是简单工厂作为创建型模式的基本要求,虽然简单,也值得我们学习一番。

简单工厂(Simple Factory)模式

上面提到,简单工厂提供了创建型模式的基本功能,完成对对象创建的封装。其使用场景主要在当Product的种类太多导致类型名混乱时,使用对Factory传入参数的不同来区分不同种类的Product。注意: 以上所说的种类是指所有Product类均派生自同一基类,否则无法用参数将其区别开来。(参数就是它们属于同一基类的体现)

举个栗子:某车厂现生产多种品牌的车BWM 和 NIO等. 我们将其基本的功能属性抽象出父类Car,通过一个函数CreateCar的传入参数不同,确认生成的是那个子类的具体实例,返回基类指针. 这样我们就可以将对象的生成参数化,控制相同基类的子类对象的生成.
image

//car.hpp

#include <iostream>

#ifndef _DESIGN_PATTERN_SIMPLE_FACTORY_CAR_HPP_
#define _DESIGN_PATTERN_SIMPLE_FACTORY_CAR_HPP_

namespace design_pattern
{
class Car
{
public:
	virtual void name() = 0;
};

class BMW : public Car
{
public:
	void name()
	{
		std::cout << "my name is BMW" << std::endl;
	}
};

class NIO : public Car
{
public:
	void name()
	{
		std::cout << "my name is NIO" << std::endl;
	}
};
}

#endif //_DESIGN_PATTERN_SIMPLE_FACTORY_CAR_HPP_

//factory_car.hpp

#include "car.hpp"
#include <string>

#ifndef _DESIGN_PATTERN_SIMPLE_FACTORY_FACTORYCAR_HPP_
#define _DESIGN_PATTERN_SIMPLE_FACTORY_FACTORYCAR_HPP_


namespace design_pattern
{
class FactoryCar
{
public:

	Car * CreateCar(std::string const &name)
	{
		if (name == std::string("BMW"))
			return new BMW;
		if (name == std::string("NIO"))
			return new NIO;
		return NULL;
	}
};
}

#endif //_DESIGN_PATTERN_SIMPLE_FACTORY_FACTORYCAR_HPP_

//simple_factory_main.cpp

#include "car.hpp"
#include "factory_car.hpp"
using namespace design_pattern;

int main()
{
    FactoryCar fac;
    Car *pbmw = fac.CreateCar("BMW");
    Car *pnio = fac.CreateCar("NIO");
    pbmw->name();
    pnio->name();
    
    return 0;
}

显然,BMW与NIO都是由Car派生而来,在CreateCar函数中,由于其都对string name参数感兴趣才在创建时区分出了BMW与NIO。这就造成,当类进行扩展时,就要去修改CreateCar函数。也就是,若共工厂产品出现变化,NIO停产或者加入新的类型的车,这时我们需要将之前的CreateCar方法修改,造成对原有代码的入侵.不符合开放封闭原则

工厂方法(Factory Method)模式

由于产品体系过于庞大,产品体系出现分层现象。我们之前的简单工厂只能在同一层内区别产品的不同。当产品出现产品树时,我们的工厂模式也进一步以树形进行分层抽象完成在叶子节点的创建,在中间节点的使用的功能。工厂方法模式也就此形成。

注意: 虽然工厂方法模式完成了产品的分层抽象及创建,但其依然局限于同类产品,所有产品必须拥有一个共同的基类。

假设,在FactoryCar中,我们并不知道它们可以通过name区分开来,因为这个类太过笼统。但我们知道在FactoryCar的子类中,随着工厂的逐步细化,在其子类FactoryBMW与FactoryNIO中我们就可以知道其创建的具体对象。

image

//car.hpp 与simple_factory中一致

//factory_car_series.hpp

#include "car.hpp"
#ifndef _DESIGN_PATTERN_FACTORY_METHOD_FACTORY_CAR_SERIES_HPP_
#define _DESIGN_PATTERN_FACTORY_METHOD_FACTORY_CAR_SERIES_HPP_

namespace design_pattern
{

class FactoryCarBase
{
public:
	virtual Car * CreateCar() = 0;
};

class FactoryBMW : public FactoryCarBase
{
public:
	Car * CreateCar()
	{
		return new BMW;
	}
};

class FactoryNIO : public FactoryCarBase
{
public:
	Car * CreateCar()
	{
		return new NIO;
	}
};

}

#endif //_DESIGN_PATTERN_FACTORY_METHOD_FACTORY_CAR_SERIES_HPP_

//factory_method_main.cpp

#include "car.hpp"
#include "factory_car_series.hpp"
using namespace design_pattern;

int main()
{
	FactoryBMW fbmw;
	FactoryCarBase *pfac_base = &fbmw;
	Car *bmw = pfac_base->CreateCar();
	bmw->name();

	FactoryNIO fnio;
	pfac_base = &fnio;
	Car *nio = pfac_base->CreateCar();
	nio->name();
	
	return 0;
}

显然,在父类FactoryCarBase中,我们并不知道创建那种Car,只有在其子类中我们才知道具体创建的种类。

当然,如果我们嫌FactoryCarBase通过继承方式太过浪费,那也可以采用之前的参数化工厂方法实现。

语法tips
  • 相同namesapce中,无需再声明using即可使用。
  • 编译器为一个类默认提供缺省成员函数均为public. example: class Test
    1. Test()
      //constructor
    2. ~Test()
      //destructor
    3. Test(Test const&)
      //copy constructor
    4. Test const& operator=(Test const&)
      //assignment operator reload
    5. Test* operator&()
      //address-of operator reload
    6. Test const* operator()const
      //const address-of operator reload
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值