C++创建型模式——工厂模式(简单、方法、抽象) 超详细举例说明

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

写这一系列之前,我也是在开发中越来越重视开发模式,同时也是整理了一番。各种开发模式多而杂,乱而又相似,写这些东西也是为了记录和巩固,要是有不同见解欢迎随时指正。

为什么我们要在软件开发中使用设计模式,我认为以下三点总结的是很到位的:

  1. 为了代码可重用性、增加可维护性,让代码更容易被他人理解、保证代码可靠性。设计模式使代码编写真正工程化。

  2. 设计模式已经经历了很长一段时间的发展,它们提供了软件开发过程中面临的一般问题的最佳解决方案。学习这些模式有助于经验不足的开发人员通过一种简单快捷的方式来学习软件设计。

  3. 能够使我们的代码更加结构化,清晰明了

|版本声明:山河君,未经博主允许,禁止转载

一、工厂模式是什么?

工厂模式是属于创建型模式的一种,主要分为简单工厂模式、工厂方法模式、抽象工厂模式,是为了隐藏创建逻辑而创建对象的一种方法。

有部分同学刚看到简单工厂啊,工厂方法模式啊,就认为这三种模式是进阶的,当然这么理解是没有错,但是在实际应用中,并没有说工厂方法模式就比简单工厂好,或者能用抽象工厂就可以用工厂方法,一切都要为了适合。

在了解创建型模式时,需要特别关注的是对象的创建,这样有助于理解不同的创建型模式之间的区别,否则会专注于各种实现的方法,而觉得这些模式看起来并没有什么不同。

二、简单工厂模式

1.核心:

  • 简单工厂(SimpleFactory):是简单工厂模式的核心,负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
  • 抽象产品(Product):是简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口。
  • 具体产品(ConcreteProduct):是简单工厂模式的创建目标。

2.实例:

大多人都会举例工厂生产产品,可能是因为工厂模式不举例工厂有点说不过去,但是又会给初学者一种知道了这种模式的含义而不知道使用场景是什么。

如果我们能把各种子类通过抽象,能够找到同一父类,那么我们基本都可以使用工厂模式来隐藏创建逻辑。

比如:现在有一个长方形Rectangle 和正方形类Square ,抽象出的父类是形状类shape,我们创建长方形类的逻辑是长宽不一致,正方形的逻辑是长宽相等:

#include <iostream>

using namespace std;

class shape	//形状类
{
public:
	virtual void show() = 0;
};

class Square : public shape //正方形类
{
public:
	void show() { cout << "this is square" << endl; }
};

class Rectangle : public shape //长方形类
{
public:
	void show() { cout << "this is rectangle" << endl; }
};

class factory //这就是工厂
{
public:
	factory() {};
	~factory() {};
	shape* create(int x, int y) //创建逻辑
	{
		if (x == y)
			return new Square;
		else
			return new Rectangle;
	}
};

在工厂类中就隐藏了创建的逻辑,使用者不需要关心如何创建出来一个形状类,直接使用就可以。

3.缺点:

如果我们现在有第三种形状圆形,创建逻辑是:如果x,y都是0,那么它是圆形,这个其实很好加修改代码

  1. 创建一个Circular 继承 shape:
  2. 在工厂类中加入判断x,y都为0,则创建圆形类

但是我们是不是违反了大名鼎鼎的开闭原则,可扩展不可修改,有没有发现工厂类里的逻辑是不是被修改了? 所以简单工厂模式并不完美。

三、工厂方法模式

1.核心

上面说到简单工厂模式是由简单工厂、抽象产品、具体产品构成的,但是如果增加了某一类具体产品,就要修改工厂创建产品的逻辑,这就违反了开闭原则。而工厂方法模式就是在此基础上增加了抽象工厂,而满足于扩展性。

  • 抽象工厂(Abstract Factory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
  • 具体工厂(ConcreteFactory):主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
  • 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
  • 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。

工厂方法模式是把对象的创建放在了工厂子类里,所以有很好的扩展性。

2.举例

例如:

#include <iostream>

using namespace std;

class shape	//形状类
{
public:
	virtual void show() = 0;
};

class SquareRed : public shape //正方形类
{
public:
	void show() { cout << "this is red square" << endl; }
};

class SquareYellow : public shape //正方形类
{
public:
	void show() { cout << "this is Yellow square" << endl; }
};

class Rectangle : public shape //长方形类
{
public:
	void show() { cout << "this is rectangle" << endl; }
};

class factory //这就是工厂
{
public:
	virtual shape* create(int color) = 0;
};

class factory1 : public factory	//正方形工厂
{
public:
	shape* create(int color) {
		switch (color)
		{
		case 1:
			return new SquareRed;
		case 2:
			return new SquareYellow;
		}
	}
};

class factory2 : public factory //长方形工厂
{
public:
	shape* create(int color) { return new Rectangle; }
};


factory* fun()
{
	return new factory1;//外界只要知道有个factory* 父类指针就可以创建正方形了
}

3.缺点

看起来是不是很像俄罗斯套娃??看到这有可能有人就迷糊了:

  1. 这样写不还是多了一层创建工厂的逻辑?什么时候创建正方形工厂什么时候创建长方形工厂?
  2. 每次增加产品都需要增加一个工厂类图啥?

还请注意我们实际目的是什么,是为了创建shape对象,

其实这些都是工厂方法模式的缺点:

  • 类的个数容易过多,增加复杂度
  • 增加了系统的抽象性和理解难度

那么我们为什么还要使用它?
在一开始就说了,工厂方法模式是为了解决简单工厂模式扩展性而多了一个工厂抽象类,而当需要生成的产品不多且不会增加,一个具体工厂类就可以完成任务时,可删除抽象工厂类。这时工厂方法模式将退化到简单工厂模式。

读者可以思考一下如果我们可能会创建蓝色的长方形对象,红色的长方形对象该怎么实现

四、抽象工厂模式

1.核心

一部分同学觉得这三种工厂模式是进阶的,而个人理解抽象工厂和之前两种都不同。不同的地方在抽象工厂模式是为了产品族服务的。

这种方法的出现的目的是:在创建一族对象时,只能够创建这一族里的东西

2.实例

什么叫产品族呢?
比如:现在要生产长方形和笔盒、正方形和魔方,而长方形和笔盒是同一批次生产的,正方形和魔方是同一生产的

  • 长方形和正方形是同一等级(shape父类),魔方和笔盒是同一等级(product父类)
  • 长方形和笔盒是同一产品族,正方形和魔方是同一产品族

现在写成工厂模式很容易看出来有一个 玩具工厂和文具工厂:

#include <iostream>

using namespace std;

class shape	//形状类
{
public:
	virtual void show() = 0;
};

class Square : public shape //正方形类
{
public:
	void show() { cout << "this is square" << endl; }
};

class Rectangle : public shape //长方形类
{
public:
	void show() { cout << "this is rectangle" << endl; }
};

class product
{
public:
	virtual void name() = 0;
};

class Cube : public product
{
public:
	virtual void name() { cout << "this is Cube" << endl; };
};

class Pencase : public product
{
public:
	virtual void name() { cout << "this is Pencase" << endl; };
};

class factory //这就是工厂
{
public:
	virtual shape* create() = 0;
	virtual product* createPro() = 0;
};

class factory1 : public factory	//正方形工厂
{
public:
	shape* create() { return new Square; }
	product* createPro() { return new Cube; }
};

class factory2 : public factory //长方形工厂
{
public:
	shape* create() { return new Rectangle; }
	product* createPro() { return new Pencase; }
};


factory* fun()
{
	return new factory1;//外界只要知道有个factory* 父类指针就可以创建正方形了
}

3.缺点

产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值