以C/C++语法浅谈二十三种设计模式(一)——工厂模式(Factory Method)

版权声明:版权所有,转载请注明出处 https://blog.csdn.net/weixin_39951988/article/details/85758009

0.写在前面

在软件开发过程中,为了提高开发效率、增强软件运行的稳定性,降低后期项目维护的成本,我们志在追求更加高效、简单的设计思路来引领我们的项目产品,在经过不断的探索与总结的过程中,我们最常用的设计模式有23中,总体分为三大类,即创建型模式、结构型模式和行为型模式,具体如下:

模式分类 具体模式
创建型模式 工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
结构型模式 适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
行为型模式 策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式

本篇以最常用的工厂模式进行讲起,工厂模式主要包含静态工厂模式(又叫静态工厂模式)、工厂方法模式和抽象工厂模式三类。

一.静态工厂模式(简单工厂模式)

1. 简单介绍

静态工厂模式是工厂模式中最简单的一种,它可以用比较简单的方式隐藏创建对象的细节,一般只需要告诉工厂类所需要创建的类型,工厂类就会返回需要的类对象,而客户端看到的也只是类的抽象对象(interface),因此无需关心到底是返回了哪个子类。
2.组成
静态工厂模式由工厂类对象、抽象产品类对象、具体产品类对象组成。
1)工厂类对象:这是本模式的核心,含有一定的判断逻辑,根据逻辑和需求的不同,产生具体的产品角色;
2)抽象产品类对象:它是具体产品的父类或者基类,提供具体实现的接口和方法;
3)具体产品类对象:它是抽象产品类对象派生出来的具体产品对象,对抽象产品类对象的接口方法进行实例化,实现自有的方法。

想象一下,现在的你是一家大型公司的老董,你公司旗下在全国各地都有自己的分公司,反正你是老总,年底了你最关心的是各家分公司给你赚取了多少钱的利润,至于具体是怎么赚的可能是经理、或者员工该关心的事。而公司我们可以将其理解为挣钱的工厂
我们首先看下有关这个公司(工厂)的UML图:
在这里插入图片描述

3. 实例代码
首先,我们定义一个公司基类,像这样:

#include <iostream>
using namespace std;

class Company
{
public:
	Company(){}
	virtual~Company(){}
public:
	virtual const std::string GetMoney()const = 0;
};

然后各分公司继承公司基类汇报自己的营业额,像这样:

//北京分公司
class BeiJingCompany:public Company
{
public:
	virtual const std::string GetMoney()const
	{
		return "北京赚了一个亿";
	}
};
//武汉分公司
class WuHanCompany:public Company
{
public:
	virtual const std::string GetMoney()const
	{
		return "武汉赚了五千万";
	}
};
//广州分公司
class GuangZhouCompany:public Company
{
public:
	virtual const std::string GetMoney()const
	{
		return "广州赚了八千万";
	}
};

然后我们定义我们的工厂类,像这样:

enum COMPANYNAME{BEIJING,WUHAN,GUANGZHOU};
class CompanyFactory
{
public:
	Company* CreateCompany(COMPANYNAME companyName)
	{
		switch(companyName)
		{
		case BEIJING:
			{
                return new BeiJingCompany();
			}break;
		case WUHAN:
			{
				return new WuHanCompany();
			}break;
		case GUANGZHOU:
			{
				return new GuangZhouCompany();
			}break;
		default:break;
		}
	}
};

到了这一步,我们的董事长来了,他想知道每个分公司今年各赚了多少钱,于是像下面这样:

int main(int argc, char *argv[])
{
	CompanyFactory* factoryCompany = new CompanyFactory();
	if(factoryCompany)
	{
		Company* beijingCompany = factoryCompany->CreateCompany(BEIJING);
		beijingCompany->GetMoney();

		Company* wuhanCompany = factoryCompany->CreateCompany(WUHAN);
		wuhanCompany->GetMoney();

		Company* guangzhouCompany = factoryCompany->CreateCompany(GUANGZHOU);
		guangzhouCompany->GetMoney();
	}
	delete factoryCompany;
	factoryCompany = NULL;
	return 0;
}

二.工厂方法模式

1. 引子
随着公司越做越大,你的分公司在短短的几年时间里已经遍布全国各地,最近还想扩展海外市场,每开设一家分公司,我们就要在工厂类里添加新公司,这可累坏我们的工厂类,于是工厂方法模式就这样登场了。
2. 组成
**工厂方法模式由抽象工厂类对象、具体工厂类对象、抽象产品类对象、具体产品类对象组成。
1)抽象工厂类对象: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂类对象必须实现的接口或者必须继承的父类(基类)。
2)具体工厂类对象:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
3)抽象产品类对象:它是具体产品继承的父类或者是实现的接口。
4)具体产品类对象:具体工厂角色所创建的对象就是此角色的实例。
工厂方法模式UML图如下:
**
在这里插入图片描述

3.实例代码
首先定义一个抽象工厂基类和一个抽象产品基类,像这样:

//抽象公司基类
class CompanyBase
{
public:
	CompanyBase(){}
	virtual~CompanyBase(){}

	virtual const std::string GetMoney()const = 0;
};
//抽象工厂基类
class FactoryBase
{
public:
	FactoryBase(){}
	virtual ~FactoryBase(){}
	virtual const CompanyBase* CreateCompany() const = 0;
};

然后定义具体的工厂类和具体的产品类,像这样:

//北京产品实例化
class BeiJingCompany:public CompanyBase
{
public:
	virtual const std::string GetMoney()const
	{
		return "北京赚了一个亿";
	}
};
//北京工厂实例化类
class BeiJingFactory:public FactoryBase
{
public:

  virtual const CompanyBase* CreateCompany() const
  {
	  return new BeiJingCompany();
  }
};
//武汉产品具体实现类
class WuHanCompany:public CompanyBase
{
public:
	virtual const std::string GetMoney()const
	{
		return "武汉赚了五千万";
	}
};
//武汉工厂具体实现类
class WuHanFactory:public FactoryBase
{
public:

	virtual const CompanyBase* CreateCompany() const
	{
		return new WuHanCompany();
	}
};
//广州产品具体实现类
class GuangZhouCompany:public CompanyBase
{
public:
	virtual const std::string GetMoney()const
	{
		return "广州赚了八千万";
	}
};
//广州工厂具体实现类
class GuangZhouFactory:public FactoryBase
{
public:

	virtual const CompanyBase* CreateCompany() const
	{
		return new GuangZhouCompany();
	}
};

好了到我们的大Boss董事长登场了

int main(int argc, char *argv[])
{
	FactoryBase* factoryBeijing = new BeiJingFactory();
	CompanyBase* beijingCompany = factoryBeijing->CreateCompany();
	beijingCompany->GetMoney();

	FactoryBase* factoryWuhan = new WuHanFactory();
	CompanyBase* wuhanCompany = factoryWuhan->CreateCompany();
	wuhanCompany->GetMoney();

	FactoryBase* guangzhouWuhan = new GuangZhouFactory();
	CompanyBase* guangzhouCompany = guangzhouWuhan->CreateCompany();
	guangzhouCompany->GetMoney();
	return 0;
}

可以看出,每个工厂只生产某一种产品,不同的工厂生产不同的产品,而具体该生产哪一种产品的逻辑交给客户端这边进行处理。

三.抽象工厂模式

1.引子
随着公司不断发展壮大,单一的业务已经不能满足日益发展的社会,我们准备开展公司的第二业务路线,在各地分公司进行实行,为了适应后续随着公司的不断发展可能增加的更多的业务路线,我们引出了抽象工厂模式
2. 组成
抽象工厂模式的组合和工厂方法模式的组合一样,也是由抽象工厂类对象、具体工厂类对象、抽象产品类对象、具体产品类对象组成。

3.实例代码
由于现在我们增加了第二业务路线,我们首先定义两个业务的基类,如下:

//第一业务基类
class ProductBaseOne
{
public:
	ProductBaseOne(){}
	virtual ~ProductBaseOne(){}
public:
	virtual std::string GetMoney() = 0;
};
//第二业务基类
class ProductBaseTwo
{
public:
	ProductBaseTwo(){}
	virtual ~ProductBaseTwo(){}
public:
	virtual std::string GetMoney() = 0;
};

然后定义各个分公司的业务类,实现接口方法,如下所示:

//北京第一业务营业额
class BeiJingCompanyOne:public ProductBaseOne
{
public:
	virtual std::string GetMoney() 
	{
       return "北京第一业务赚了一个亿";
	}
};
//北京第二业务营业额
class BeiJingCompanyTwo:public ProductBaseTwo
{
public:
	virtual std::string GetMoney() 
	{
		return "北京第二业务赚了八千万";
	}
};

//武汉第一业务营业额
class WuhanCompanyOne:public ProductBaseOne
{
public:
	virtual std::string GetMoney() 
	{
		return "武汉第一业务赚了一个亿";
	}
};

//武汉第二业务营业额
class WuhanCompanyTwo:public ProductBaseTwo
{
public:
	virtual std::string GetMoney() 
	{
		return "武汉第二业务赚了一个亿";
	}
};

//广州第一业务营业额
class GuangzhouCompanyOne:public ProductBaseOne
{
public:
	virtual std::string GetMoney() 
	{
		return "广州第一业务赚了一个亿";
	}
};

//广州第二业务营业额
class GuangzhouCompanyTwo:public ProductBaseTwo
{
public:
	virtual std::string GetMoney() 
	{
		return "广州第二业务赚了五千万";
	}
};

接着定义一个工厂接口,分别创建第一、第二业务类对象

//工厂接口父类(基类)
class FactoryProductBase
{
public:
	FactoryProductBase(){}
	virtual~FactoryProductBase(){}

public:
	virtual ProductBaseOne* CreateProductOne() = 0;    //生成第一业务对象

	virtual ProductBaseOne* CreateProductTwo() = 0;    //生成第二业务对象
};

class BeijingCompanyFactory:public FactoryProductBase
{
public:
	virtual ProductBaseOne* CreateProductOne()
	{
		return new BeiJingCompanyOne();
	}

	virtual ProductBaseTwo* CreateProductTwo()
	{
		return new BeiJingCompanyTwo();
	}
};

class WuhanCompanyFactory:public FactoryProductBase
{
public:
	virtual ProductBaseOne* CreateProductOne()
	{
		return new WuhanCompanyOne();
	}

	virtual ProductBaseTwo* CreateProductTwo()
	{
		return new WuhanCompanyTwo();
	}
};

class GuangzhouCompanyFactory:public FactoryProductBase
{
public:
	virtual ProductBaseOne* CreateProductOne()
	{
		return new GuangzhouCompanyOne();
	}

	virtual ProductBaseTwo* CreateProductTwo()
	{
		return new GuangzhouCompanyTwo();
	}
};

最后,在我们的高级逻辑模块可按如下方法进行调用:

int main(int argc, char *argv[])
{
	FactoryProductBase* beijingCompany = new BeijingCompanyFactory();
	ProductBaseOne* beijingProductOne = beijingCompany->CreateProductOne();
	ProductBaseTwo* beijingProducttwo = beijingCompany->CreateProductTwo();
	beijingProductOne->GetMoney();
	beijingProducttwo->GetMoney();

	FactoryProductBase* wuhanCompany = new WuhanCompanyFactory();
	ProductBaseOne* wuhanProductOne = wuhanCompany->CreateProductOne();
	ProductBaseTwo* wuhanProducttwo = wuhanCompany->CreateProductTwo();
	wuhanProductOne->GetMoney();
	wuhanProducttwo->GetMoney();

	FactoryProductBase* guangzhouCompany = new GuangzhouCompanyFactory();
	ProductBaseOne* guangzhouProductOne = guangzhouCompany->CreateProductOne();
	ProductBaseTwo* guangzhouProducttwo = guangzhouCompany->CreateProductTwo();
	guangzhouProductOne->GetMoney();
	guangzhouProducttwo->GetMoney();
	
	return 0;
}

从上可以看出,之所以叫抽象工厂,是因为跟工厂方法相比,这里会存在多个抽象产品类(第一业务产品和第二产品业务)而工厂接口有多个方法,用来产生出不同的抽象产品。

四.总结

准确来说,简单工厂模式不属于常用的设计模式之一,因为它违背了六大设计原则之一的开闭原则(后期会专门针对开闭设计原则进行总结)。简单工厂模式适用于需要创建的对象比较少的情况,高层模块通过传参就可获取获取到自己想要的对象。
工厂方法模式主要针对单一产品结构的情况,当产品模块增多或者逻辑变得复杂的时候使用工厂方法模式就需要改动很多的代码,增加不必要的冗余。
抽象工厂模式则是针对多级产品结构(系列产品)的一种工厂模式。它将产品的方法和实现相分离,降低了代码之间的耦合性,方便项目的后期维护。在增减新对象时只需要添加新工厂方法就可以实现,无需改动大量的代码。

猜你喜欢

转载自blog.csdn.net/weixin_39951988/article/details/85758009