设计模式(二)简单工厂

面向对象的程序中,对象的创建是一件非常重要的事情。

简单工厂,就是将类的具体对象当做一个个产品,通过一个加工工厂,把这些产品创建出来,简单工厂模式,核心就是这个创建产品的工厂。

这个模式的使用频率非常大。

很多公司,根据员工能力不同,会将员工分为很多级别,不同级别的员工工资不一样。下面就以这个例子(这个例子会一直扩展下去),介绍一下简单工厂。

想实现不同职级不同公司,很容易想到多态。一个员工职级的基类,定义一个虚函数获取工资,不同职级,从这个基类派生,重写获取工资的虚函数。

看代码(visual studio 2019):

#pragma once

#include <iostream>
#include <list>


class GradeBase
{
public:
	GradeBase(const std::string& strName) :m_strName(strName) {}
	virtual ~GradeBase() = default;

	std::string GetName() const { return m_strName; }
	virtual double GetSalary() = 0;

protected:
	std::string m_strName;  //姓名
};

class Grade_1 : public GradeBase
{
public:
	using GradeBase::GradeBase;
	double GetSalary() override {
		return 5000;
	}
};

class Grade_2 : public GradeBase
{
public:
	using GradeBase::GradeBase;
	double GetSalary() override {
		return 8000;
	}
};

class SimpleFactory
{
public:
	static std::unique_ptr<GradeBase> GetLevel(const std::string& strName, int iLevel){
		if (1 == iLevel)
			return std::make_unique<Grade_1>(strName);
		else if (2 == iLevel)
			return std::make_unique<Grade_2>(strName);
		return nullptr;
	}
};


int main()
{
	std::list<std::unique_ptr<GradeBase>> lstEmployee;
	lstEmployee.push_back(SimpleFactory::GetLevel("David", 1));
	lstEmployee.push_back(SimpleFactory::GetLevel("Tom", 2));
	lstEmployee.push_back(SimpleFactory::GetLevel("Lucas", 3));

	for (const auto& employee : lstEmployee)
	{
		if (!employee)
			continue;
		std::cout << employee->GetName() << "薪资:" << employee->GetSalary() << "\n";
	}

	system("pause");
	return 0;
}

以上实现方式,是为了尽可能让代码逻辑简单,有很多不妥,比如直接用等级类来表示职工、未考虑同一员工职级会改变等等,之后会以这个为原型,逐步改进。

基类GradeBase,只有一个变量,表示职工名称,纯虚函数GetSalary获取工资。

不同职级,从GradeBase派生,重写虚函数GetSalary。

SimpleFactory类,就是这个设计模式的核心,提供一个接口,传入职工名称和等级编号,根据编号,用不同的类实例化具体员工。

如果仅仅是这个例子,SimpleFactory存在的必要性不大,因为它的功能完全可以用一个函数替代。类似如下函数:

std::unique_ptr<GradeBase> GetGrade(const std::string& strName, int iLevel)
{
	if (1 == iLevel)
		return std::make_unique<Grade_1>(strName);
	else if (2 == iLevel)
		return std::make_unique<Grade_2>(strName);
	return nullptr;
}

但是,不要用函数,用类!后面的文章,会对这个类进行扩展,展现简单工厂的真正实用之处。

main函数其实就是客户端,也是调用者,传入不同的员工和等级编号,获取具体的对象。

执行结果如下:

设计模式(二)简单工厂

为什么只有两个对象?

因为Lucas传入的等级是3,在GetLevel接口中没有与之对象的创建对象的条件,所以这个对象为nullptr。

这就有个问题了,等级需要扩展怎么办?

简单工厂模式,只能修改GetLevel接口的实现,增加if条件判断,有没有不修改工厂类的方式?当然有,请看下篇文章介绍。

 

 

上一篇:thinkphp使用验证器校验编辑数据,提示重复


下一篇:P3913 车的攻击