C++设计模式[一]工厂模式

本文深入浅出地介绍了C++中的工厂模式,包括简单工厂模式、工厂方法模式和抽象工厂模式,通过实例代码展示了每种模式的应用场景及优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一直想好好学习一下设计模式,终于发现了一个通熟易懂的C++设计模式解释,最近有点懒,然后大部分内容掌握一下就转过来了,其中有些注释自己加的,有什么错误,请指正,谢谢。

================================================================================================

对于中间代码实现和大部分内容归作者所有,仅供参考学习,对于文章属于转载还是原创问题,请原谅,有自己写的都划分到原创

                                                                     这一栏,全部转载划分为转载这一栏

================================================================================================

 

首先看一下这些模式:

创建模式

简单工厂模式:由工厂决定生产哪一种产品,选择了什么工厂就生产什么样的产品【不算一种设计模式】

工厂方法模式:定义工厂接口,由具体工厂决定生产什么样的产品

抽象工厂模式:提供接口,创建一系列相关或独立的对象,而不指定这些对象的具体类

单例模式:在整个系统中只存在对象的一个实例

建造者模式:使用同样的建造过程创建不同的实例

原型模式:通过克隆/复制一个已经存在的实例创建新的对象

结构模式

适配器模式:将具有A接口外观的对象转换成具有B接口外观的对象,但仍由A类型对象执行底层操作

桥接模式:将行为和动作进行分离,使之可以独立进行变化

组合模式:将一组对象当作一个对象看待,执行组合的方法,该组对象的方法都会被调用

装饰者模式:动态的给对象添加功能

外观模式:将一组行为进行包装,简化外部调用

享元模式:将公共使用的东西抽取出来共同使用

代理模式:一个类作为其他类的接口,供客户调用

行为模式

责任链模式:将职责进行封装,串联成链式并定义其流转行为,同时可以进行动态扩充职责

命令模式:将行为封装成命令使其具有统一外观,方便统一调用执行

解释器模式:使用抽象表示代替详细描述

迭代器模式:封装不同集合的遍历方法,使其具有统一的外观

中介模式:使用中介对象进行各对象间的交互,避免对象内嵌交互,降低耦合

备忘录模式:类似闭包功能,在不破坏对象封装的情况下,保存对象的细节,以便于恢复到该状态

观察者模式:一个对象的变化会影响到其他对象

状态模式:根据状态的转移而选择不同的状态类进行处理相应的业务逻辑

策略模式:定义算法族,分别封装起来,让他们直接可以相互替换,使算法的变化独立于使用算法的客户

模板方法模式:类似工厂方法模式,将同一类对象中相同操作进行抽取,不同的操作进行抽象,由具体类进行实现

访问者模式:在不改变元素的类的前提下定义作用于这些元素的新操作

=====================================================================

首先是工厂模式;

工厂模式有一种非常形象的描述,建立对象的类就如一个工厂,而需要被建立的对象就是一个个产品;在工厂中加工产品,使用产品的人,不用在乎产品是如何生产出来的。从软件开发的角度来说,这样就有效的降低了模块之间的耦合。

UML类图

对于工厂模式,具体上可以分为三类:

  1. 简单工厂模式;
  2. 工厂方法模式;
  3. 抽象工厂模式。

对于上面的三种工厂模式,从上到下逐步抽象,并且更具一般性。这篇主要讲的是简单工厂模式。
Simply Factory DesignProductA、ProductB和ProductC继承自Product虚拟类,Show方法是不同产品的自描述;Factory依赖于ProductA、ProductB和ProductC,Factory根据不同的条件创建不同的Product对象。

适用场合

  1. 在程序中,需要创建的对象很多,导致对象的new操作多且杂时,需要使用简单工厂模式;
  2. 由于对象的创建过程是我们不需要去关心的,而我们注重的是对象的实际操作,所以,我们需要分离对象的创建和操作两部分,如此,方便后期的程序扩展和维护。

 

#include "stdafx.h"
#include <string>
#include<iostream>
using namespace std;
class Product
{
public:
	virtual void use(){};
};
class ConcreteProductA :public Product
{
public:
	void use()
	{
		cout << "使用A" << endl;
	};
};
class ConcreteProductB:public Product
{
public:
	void use()
	{
		cout << "使用B" << endl;
	};
};
class Factory
{
public:
	Product* Factory::createProduct(string proname){
		if ("A" == proname)
		{
			return new ConcreteProductA();
		}
		else if ("B" == proname)
		{
			return new ConcreteProductB();
		}
		return  NULL;
	}
};
int main()
{
	Product *P = NULL;
	Product *Q = NULL;
	Factory f;
	P=f.createProduct("A");
	Q = f.createProduct("B");
	P->use();
	Q->use();
	return 0;
}

 

 

 

 

 

 

由于简单工厂模式的局限性,比如:工厂现在能生产ProductA、ProductB和ProductC三种产品了,此时,需要增加生产ProductD产品;那么,首先是不是需要在产品枚举类型中添加新的产品类型标识,然后,修改Factory类中的switch结构代码。是的,这种对代码的修改,对原有代码的改动量较大,易产生编码上的错误(虽然很简单,如果工程大了,出错也是在所难免的!!!)。这种对代码的修改是最原始,最野蛮的修改,本质上不能称之为对代码的扩展。同时,由于对已经存在的函数进行了修改,那么以前进行过的测试,都将是无效的,所有的测试,都将需要重新进行,所有的代码都需要进行重新覆盖。这种,增加成本,不能提高效率的事情,在公司是绝对不允许的(除非昏庸的PM)。出于种种原因,简单工厂模式,在实际项目中使用的较少。那么该怎么办?怎么办呢?需要对原有代码影响降到最小,同时能对原有功能进行扩展。

UML类图

工厂方法模式是对简单工厂模式的扩展,在GOF的介绍中,它们是合并在一起的,而我则是单独分开进行讲解的,就是为了区分二者的利弊,便于大家在实际项目中进行更好的把握与应用。工厂方法模式是在简单工厂模式的基础上,对“工厂”添加了一个抽象层。将工厂共同的动作抽象出来,作为抽象类,而具体的行为由子类本身去实现,让子类去决定生产什么样的产品。

果冻想 | 一个原创文章分享网站

如图,FactoryA专心负责生产ProductA,FactoryB专心负责生产ProductB,FactoryA和FactoryB之间没有关系;如果到了后期,如果需要生产ProductC时,我们则可以创建一个FactoryC工厂类,该类专心负责生产ProductC类产品。由于FactoryA、FactoryB和FactoryC之间没有关系,当加入FactoryC加入时,对FactoryA和FactoryB的工作没有产生任何影响,那么对代码进行测试时,只需要单独对FactoryC和ProductC进行单元测试,而FactoryA和FactoryB则不用进行测试,则可省去大量无趣无味的测试工作。

适用场合

工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。

  1. 在设计的初期,就考虑到产品在后期会进行扩展的情况下,可以使用工厂方法模式;
  2. 产品结构较复杂的情况下,可以使用工厂方法模式;

由于使用设计模式是在详细设计时,就需要进行定夺的,所以,需要权衡多方面的因素,而不能为了使用设计模式而使用设计模式。

 

#include"stdafx.h"
#include <iostream>
#include <vector>
using namespace std;

class Product
{
public:
	virtual void Show() = 0;
};

class ProductA : public Product
{
public:
	void Show()
	{
		cout << "I'm ProductA" << endl;
	}
};

class ProductB : public Product
{
public:
	void Show()
	{
		cout << "I'm ProductB" << 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();
	}
};

int main(int argc, char *argv[])
{
	Factory *factoryA = new FactoryA();
	Product *productA = factoryA->CreateProduct();
	productA->Show();

	Factory *factoryB = new FactoryB();
	Product *productB = factoryB->CreateProduct();
	productB->Show();

	if (factoryA != NULL)
	{
		delete factoryA;
		factoryA = NULL;
	}

	if (productA != NULL)
	{
		delete productA;
		productA = NULL;
	}

	if (factoryB != NULL)
	{
		delete factoryB;
		factoryB = NULL;
	}

	if (productB != NULL)
	{
		delete productB;
		productB = NULL;
	}
	return 0;
}

后期产品会越来越多了,建立的工厂也会越来越多,工厂进行了增长,工厂变的凌乱而难于管理;由于工厂方法模式创建的对象都是继承于Product的,所以工厂方法模式中,每个工厂只能创建单一种类的产品,当需要生产一种全新的产品(不继承自Product)时,发现工厂方法是心有余而力不足。

 

 

 

 

举个例子来说:一个显示器电路板厂商,旗下的显示器电路板种类有非液晶的和液晶的;这个时候,厂商建造两个工厂,工厂A负责生产非液晶显示器电路板,工厂B负责生产液晶显示器电路板;工厂一直就这样运行着。有一天,总经理发现,直接生产显示器的其余部分也挺挣钱,所以,总经理决定,再建立两个工厂C和D;C负责生产非液晶显示器的其余部件,D负责生产液晶显示器的其余部件。此时,旁边参谋的人就说了,经理,这样做不好,我们可以直接在工厂A中添加一条负责生产非液晶显示器的其余部件的生产线,在工厂B中添加一条生产液晶显示器的其余部件的生产线,这样就可以不用增加厂房,只用将现有厂房进行扩大一下,同时也方便工厂的管理,而且生产非液晶显示器电路板的技术人员对非液晶显示的其余部件的生产具有指导的作用,生产液晶显示器电路板也是同理。总经理发现这是一个不错的主意。

再回到软件开发的过程中来,工厂A和B就是之前所说的C++设计模式——工厂方法模式;总经理再次建立工厂C和D,就是重复C++设计模式——工厂方法模式,只是生产的产品不同罢了。这样做的弊端就如参谋所说的那样,增加了管理成本和人力成本。在面向对象开发的过程中,是很注重对象管理和维护的,对象越多,就越难进行管理和维护;如果工厂数量过多,那么管理和维护的成本将大大增加;虽然生产的是不同的产品,但是可以二者之间是有微妙的关系的,如参谋所说,技术人员的一些技术经验是可以借鉴的,这就相当于同一个类中的不同对象,之间是可以公用某些资源的。那么,增加一条流水线,扩大厂房,当然是最好的主意了。

实际问题已经得到了解决,那么如何使用设计模式模拟这个实际的问题呢?那就是接下来所说的抽象工厂模式。

UML类图

现在要讲的抽象工厂模式,就是工厂方法模式的扩展和延伸,但是抽象工厂模式,更有一般性和代表性;它具有工厂方法具有的优点,也增加了解决实际问题的能力。

Abstract Factory Pattern

如图所示,抽象工厂模式,就好比是两个工厂方法模式的叠加。抽象工厂创建的是一系列相关的对象,其中创建的实现其实就是采用的工厂方法模式。在工厂Factory中的每一个方法,就好比是一条生产线,而生产线实际需要生产什么样的产品,这是由Factory1和Factory2去决定的,这样便延迟了具体子类的实例化;同时集中化了生产线的管理,节省了资源的浪费。

适用场合

工厂方法模式适用于产品种类结构单一的场合,为一类产品提供创建的接口;而抽象工厂方法适用于产品种类结构多的场合,主要用于创建一组(有多个种类)相关的产品,为它们提供创建的接口;就是当具有多个抽象角色时,抽象工厂便可以派上用场。

 

#include"stdafx.h"
#include <iostream>
#include <vector>
using namespace std;

// Product A
class ProductA
{
public:
	virtual void Show() = 0;
};

class ProductA1 : public ProductA
{
public:
	void Show()
	{
		cout << "I'm ProductA1" << endl;
	}
};

class ProductA2 : public ProductA
{
public:
	void Show()
	{
		cout << "I'm ProductA2" << endl;
	}
};

// Product B
class ProductB
{
public:
	virtual void Show() = 0;
};

class ProductB1 : public ProductB
{
public:
	void Show()
	{
		cout << "I'm ProductB1" << endl;
	}
};

class ProductB2 : public ProductB
{
public:
	void Show()
	{
		cout << "I'm ProductB2" << endl;
	}
};

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

class Factory1 : public Factory
{
public:
	ProductA *CreateProductA()
	{
		return new ProductA1();
	}

	ProductB *CreateProductB()
	{
		return new ProductB1();
	}
};

class Factory2 : public Factory
{
	ProductA *CreateProductA()
	{
		return new ProductA2();
	}

	ProductB *CreateProductB()
	{
		return new ProductB2();
	}
};

int main(int argc, char *argv[])
{
	Factory *factoryObj1 = new Factory1();
	ProductA *productObjA1 = factoryObj1->CreateProductA();
	ProductB *productObjB1 = factoryObj1->CreateProductB();

	productObjA1->Show();
	productObjB1->Show();

	Factory *factoryObj2 = new Factory2();
	ProductA *productObjA2 = factoryObj2->CreateProductA();
	ProductB *productObjB2 = factoryObj2->CreateProductB();

	productObjA2->Show();
	productObjB2->Show();

	if (factoryObj1 != NULL)
	{
		delete factoryObj1;
		factoryObj1 = NULL;
	}

	if (productObjA1 != NULL)
	{
		delete productObjA1;
		productObjA1 = NULL;
	}

	if (productObjB1 != NULL)
	{
		delete productObjB1;
		productObjB1 = NULL;
	}

	if (factoryObj2 != NULL)
	{
		delete factoryObj2;
		factoryObj2 = NULL;
	}

	if (productObjA2 != NULL)
	{
		delete productObjA2;
		productObjA2 = NULL;
	}

	if (productObjB2 != NULL)
	{
		delete productObjB2;
		productObjB2 = NULL;
	}
}

 

 

 

 

 





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值