设计模式回顾——工厂模式(C++)


1 前言

  上一篇文章中对创建型设计模式之一的“单例模式”进行概述与总结,分别描述了单例模式的含义、特点、适用场以及对“饿汉式单例”和“懒汉式单例”的分析,并以C++语言实现具体例子。本文描述另一创建型设计模式——工厂模式。


2 什么是工厂模式

  工厂模式,指的是封装对象的创建过程,并将创建过程和操作过程分离,用户(创建者)无需关心具体过程,就像一个工厂生产产品一样,以便批量管理对象的创建,提高程序的可以维护性和扩展性。


  工厂模式根据“产品制造过程”(对象创建)不同,分为简单工厂模式 (Simple Factory) 、工厂方法模式 (Factory Method) 、抽象工厂模式 (Abstract Factory)


  • 简单工厂模式,由创建对象类根据传入的类型参数确定对象种类实例。简单工厂模式是工厂模式中最简单的模式,但该模式并未能体现出工厂模式的精髓。
  • 工厂方法模式,声明一个创建对象的抽象方法基类,子类继承基类,由子类创建具体对象类实例。与简单工厂模式不同,工厂方法模式的对象实例化过程由子类实现。
  • 抽象工厂模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。简单工厂和工厂方法只能创建同一类对象,抽象工厂可以创建一系列相关的对象。

  三种工厂模式特点:

工厂模式特点
简单工厂针对一种类型实例对象,违背“开闭原则”
工厂方法针对一种类型实现对象,但改正了简单工厂违背“开闭原则”的不足
抽象工厂针对多种类型实例对象

3 工厂模式优缺点

  工厂模式分为简单工厂、工厂方法、抽象工厂三种具体模式,我们分别比较三种模式的优缺点。


优点:

  • 对“职责”分离,用户不需关心创建过程
  • 外界与具体类隔离,降低耦合性
  • “工厂方法”修正了“简单工厂”不符合“开闭原则”的不足
  • “抽象工厂”综合了“简单工厂”和“工厂方法”特点,支持相关联的一系列类型对象创建

不足:

【1】简单工厂

  • 扩展性差,增加新“产品”时,需要修改工厂内部逻辑
  • 违背“开放—封闭”原则(OCP)
  • 采用静态工厂方法,无法被子类继承
  • 只能创建单一“产品”

【2】工厂方法

  • 只能创建单一“产品”
  • 一定程度增加开放工作量,每增加一个 产品,就需要增加一个子工厂

【3】抽象工厂

  • 适合生产已有种类“产品”集合,扩展新种类“产品”比较困难,因为会涉及抽象工厂类和子类的更改

4 什么地方使用工厂模式

   对于工厂模式用在什么地方,首先要了解工厂模式的用途。工厂模式用途归纳起来主要有:

  • 解耦,把对象的创建和使用的过程分开
  • 减少代码重复量
  • 降低代码维护成本

  因此,工厂模式适用场景归纳为,但不限于:

  • 对象的实例化前期工作比较繁琐复杂,如需初始化参数、读取配置文件、查询数据库等

  • 类本身存在多个子类,这些类的创建过程在业务中容易发生改变,或者对类的调用容易发生改变


4.1 三种工厂模式适用场景

  具体到细化场景,三种类型工厂模式又有不同的选择。

  • 简单工厂适用于工厂类负责创建的对象比较少的场合
  • 工厂方法适用于类不知道它所必须创建对象的类,或一个类期望由子类来创建的对象的场合
  • 抽象工厂适用于需要创建的对象是一系列相互关联或相互依赖的产品族的场合
  • 如果存在着多个等级结构(多个抽象类),且各个等级结构中的实现类之间存在着一定的关联或者约束,则考虑使用抽象工厂模式
  • 各个等级结构中的实现类之间不存在关联或约束,则考虑使用多个独立的工厂(简单工厂/工厂方法)来对产品进行创建

5 工厂模式实现

  分别对简单工厂、工厂方法、抽象工厂,使用C++实现。


5.1 简单工厂

#include <iostream> 
#include <stdlib.h> 

using namespace std;

typedef enum ProductType
{
	TypeA,
	TypeB,
	TypeC
}ProductType_t;

/* 产品抽象基类 */
class Product
{
public:
	virtual void printf() = 0;
};
class ProductA : public Product
{
public:
	void printf()
	{
		cout<<"Create productA"<<endl;
	}
};
class ProductB : public Product
{
public:
	void printf()
	{
		cout<<"Create productB"<<endl;
	}

};
class ProductC : public Product
{
public:
	void printf()
	{
		cout<<"Create productC"<<endl;
	}

};

/* 工厂类 */
class Factory
{
public:
	Product* CreateProduct(ProductType_t type);
};

Product* Factory::CreateProduct(ProductType_t type)
{
	Product *a = NULL;
	
	switch (type)
	{
		case TypeA:
			a = new ProductA();
		break;
		case TypeB:
			a = new ProductB();
		break;
		case TypeC:
			a = new ProductC();
		break;
		default:
		break;
	}
	return a;
}

int main(int argc, char **argv)
{
	Factory productCreator;
	
	Product *productA;
	Product *productB;
	Product *productC; 

	productA = productCreator.CreateProduct(TypeA);
	productB = productCreator.CreateProduct(TypeB);
	productC = productCreator.CreateProduct(TypeC);
	if(productA != NULL)
	{
		productA->printf();
		delete productA;
		productA=NULL;
	}
	if(productB != NULL)
	{
		productB->printf();
		delete productB;
		productB=NULL;
	}
	if(productC != NULL)
	{
		productC->printf();
		delete productC;
		productC=NULL;
	}
	return 0;
}


执行结果:

acuity@ubuntu:/mnt/hgfs/LSW/STHB/design-mode$ g++ factory.cpp -o factory
acuity@ubuntu:/mnt/hgfs/LSW/STHB/design-mode$ ./factory
Create productA
Create productB
Create productC

5.2 工厂方法


#include <iostream> 
#include <stdlib.h> 

using namespace std;


/* 产品抽象基类 */
class Product
{
public:
	virtual void printf() = 0;
};
class ProductA : public Product
{
public:
	void printf()
	{
		cout<<"Create productA"<<endl;
	}
};
class ProductB : public Product
{
public:
	void printf()
	{
		cout<<"Create productB"<<endl;
	}

};
class ProductC : public Product
{
public:
	void printf()
	{
		cout<<"Create productC"<<endl;
	}

};

/* 工厂类 */
class Factory
{
public:
	virtual Product* CreateProduct()=0;
};

class FactoryA:public Factory
{
public:
	Product *CreateProduct()
	{
		return new ProductA();
	}
};
class FactoryB:public Factory
{
public:
	Product *CreateProduct()
	{
		return new ProductB();
	}
};

class FactoryC:public Factory
{
public:
	Product *CreateProduct()
	{
		return new ProductC();
	}
};


int main(int argc, char **argv)
{
	Factory *factoryA;
	Factory *factoryB;
	Factory *factoryC;
	Product *productA;
	Product *productB;
	Product *productC; 

	factoryA = new FactoryA(); 
	if(factoryA != NULL)
	{
		productA = factoryA->CreateProduct(); 
		if (productA != NULL)
		{
			productA->printf();
			delete productA;
			productA = NULL;
		}
		delete factoryA;
		factoryA = NULL;
	}
	
	factoryB = new FactoryB(); 
	if(factoryB != NULL)
	{
		productB = factoryB->CreateProduct(); 
		if (productB != NULL)
		{
			productB->printf();
			delete productB;
			productB = NULL;
		}
		delete factoryA;
		factoryA = NULL;
	}
	
	factoryC = new FactoryC(); 
	if(factoryC != NULL)
	{
		productC = factoryC->CreateProduct(); 
		if (productC != NULL)
		{
			productC->printf();
			delete productC;
			productC = NULL;
		}
		delete factoryC;
		factoryC = NULL;
	}
	return 0;
}

执行结果:

acuity@ubuntu:/mnt/hgfs/LSW/STHB/design-mode$ g++ factory1.cpp -o factory1
acuity@ubuntu:/mnt/hgfs/LSW/STHB/design-mode$ ./factory1
Create productA
Create productB
Create productC

5.3 工厂抽象


#include <iostream> 
#include <stdlib.h> 

using namespace std;


/* 产品A抽象基类 */
class ProductA
{
public:
	virtual void printf() = 0;
};

/* 产品类A0 */
class ProductA0 : public ProductA
{
public:
	void printf()
	{
		cout<<"Create productA0"<<endl;
	}
};

/* 产品类A1 */
class ProductA1 : public ProductA
{
public:
	void printf()
	{
		cout<<"Create productA1"<<endl;
	}
};

/* 产品B抽象基类 */
class ProductB
{
public:
	virtual void printf() = 0;
};

/* 产品类B0 */
class ProductB0 : public ProductB
{
public:
	void printf()
	{
		cout<<"Create productB0"<<endl;
	}
};

/* 产品类B1 */
class ProductB1 : public ProductB
{
public:
	void printf()
	{
		cout<<"Create productB1"<<endl;
	}
};

/* 工厂类 */
class Factory
{
public:
	virtual ProductA* CreateProductA()=0;
	virtual ProductB* CreateProductB()=0;
};

/* 工厂类0,专门生产0类产品 */
class Factory0:public Factory
{
public:
	ProductA *CreateProductA()
	{
		return new ProductA0();
	}
	ProductB *CreateProductB()
	{
		return new ProductB0();
	}
};

/* 工厂类1,专门生产1类产品 */
class Factory1:public Factory
{
public:
	ProductA *CreateProductA()
	{
		return new ProductA1();
	}
	ProductB *CreateProductB()
	{
		return new ProductB1();
	}
};

int main(int argc, char **argv)
{
	Factory *factory0;
	Factory *factory1;
	ProductA *productA0;
	ProductA *productA1;
	ProductB *productB0; 
	ProductB *productB1;

	factory0 = new Factory0(); 
	if(factory0 != NULL)
	{
		productA0 = factory0->CreateProductA(); 
		if (productA0 != NULL)
		{
			productA0->printf();
			delete productA0;
			productA0 = NULL;
		}

		productB0 = factory0->CreateProductB(); 
		if (productB0 != NULL)
		{
			productB0->printf();
			delete productB0;
			productB0 = NULL;
		}
		delete factory0;
		factory0 = NULL;
	}
	
	factory1 = new Factory1(); 
	if(factory1 != NULL)
	{
		productA1 = factory1->CreateProductA(); 
		if (productA1 != NULL)
		{
			productA1->printf();
			delete productA1;
			productA1 = NULL;
		}

		productB1 = factory1->CreateProductB(); 
		if (productB1 != NULL)
		{
			productB1->printf();
			delete productB1;
			productB1 = NULL;
		}
		delete factory1;
		factory1 = NULL;
	}
	return 0;
}

执行结果:

acuity@ubuntu:/mnt/hgfs/LSW/STHB/design-mode$ g++ factory2.cpp -o factory2
acuity@ubuntu:/mnt/hgfs/LSW/STHB/design-mode$ ./factory2
Create productA0
Create productB0
Create productA1
Create productB1

6 参考文章

【1】创建对象与使用对象——谈谈工厂的作用
【2】工厂方法模式(Factory Method)-最易懂的设计模式解析

【目的】 如果您希望弄懂框架的原理,但是苦于不知道如何读框架源码? 希望该课程能够通过带领大家阅读源码的方式,了解源码是如何阅读的。该课程选择了一个比较小,比较简单的框架入门,相信大家应该也用过该工具——mybatis generator 【内容】 该课程内容如下,列出了具体时间,便于复习: 第一课:mybatis-generator源码分析-解析配置 这节课分为如下几段: 【00:00-05:00】:介绍源码阅读的方法 【05:00-08:00】:简介mybatis-generator的使用 【08:00-27:30】:mybatis-generator包一览 【27:30-结束】:解析配置源码解读 【总结】所在的位置:1.第一次总结【34:15】。2.第二次总结【52:40】 涉及的【设计思路】和【设计模式】:1.模板模式【15:30】。2.xml解析的对象设计+组合模式:【37:00】。3.策略模式:【45:40】 第二课:mybatis-generator源码分析-生成文件 这节课分为如下几段:        1. 【00:00-10:20】:上节课内容回顾        2. 【10:20-42:20】:如何从数据库中获取元数据信息        3. 【42:20-结束】:生成文件 【总结】所在的位置:1.第一次总结【37:45】。2.第二次总结【56:25】 涉及的【设计思路】和【设计模式】:1、简单工厂方法模式【35:20】。2、聚合的设计思想【44:00】。 第三课:mybatis-generator源码分析-总结 这节课分为如下几段:         1. 【00:00-01:00】: 设计思路总结         2. 【01:00-02:50】:配置解析总结         3. 【02:50-03:55】: 从数据库获取信息总结         4. 【03:55-结束】: 文件的生成总结         
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页