当前位置: 首页 > web >正文

深入浅出设计模式——创建型模式之简单工厂模式

文章目录

  • 设计模式的六大原则 Six principles
  • 简单工厂模式
    • 简单工厂基本实现流程
    • 简单工厂定义
    • 代码结构如下:
  • 简单工厂模式代码实例
    • 定义抽象产品类AbstractProduct,抽象方法不提供实现
    • 定义三个具体产品类
    • 定义工厂类和工厂方法
    • 客户端使用方法示例
    • 效果
    • SimpleFactory.h
    • main.cpp
    • 运行结果
  • 简单工厂模式总结

代码仓库在这

设计模式在面试中的考点通常是介绍其原理并说出优缺点。或者对比几个比较相似的模式的异同点。在笔试中可能会出现画出某个设计模式的 UML 图这样的题。虽说面试中占的比重不大,但并不代表它不重要。恰恰相反,设计模式于程序员而言相当重要,它是我们写出优秀程序的保障。设计模式与程序员的架构能力与阅读源码的能力息息相关,非常值得我们深入学习。

面向对象的特点是 可维护、可复用、可扩展、灵活性好,它最强大的地方在于:随着业务变得越来越复杂,面向对象依然能够使得程序结构良好,而面向过程却会导致程序越来越臃肿。

让面向对象保持结构良好的秘诀就是设计模式,面向对象结合设计模式,才能真正体会到程序变得可维护、可复用、可扩展、灵活性好。设计模式对于程序员而言并不陌生,每个程序员在编程时都会或多或少的接触到设计模式。无论是在大型程序的架构中,亦或是在源码的学习中,设计模式都扮演着非常重要的角色。

今天我们就一起来探索设计模式的世界!

设计模式的六大原则 Six principles

设计模式的世界丰富多彩,比如生产一个个“产品”的工厂模式,衔接两个不相关接口的适配器模式,用不同的方式做同一件事的策略模式,构建步骤稳定、根据构建过程的不同配置构建出不同对象的建造者模式等等。

无论何种设计模式,都是基于六大设计原则:

在这里插入图片描述

简单工厂模式

创建型模式关注对象的创建过程,在软件开发中应用非常广泛。创建型模式描述如何将对象的创建和使用分离,让用户在使用对象过程中无须关心对象的创建细节,从而降低系统耦合度,并且让系统易于修改和扩展。

在这里插入图片描述
什么是简单工厂模式呢?举个例子:如上图,一个体育用品生产厂(这即是一个工厂Factory),该工厂可以根据客户需求生产篮球、足球和排球。篮球、足球和排球被成为产品(Product),产品的名称可以被成为参数。客户Jungle需要时可以向工厂提供产品参数,工厂根据产品参数生产对应产品,客户Jungle并不需要关心产品的生产过程细节。

简单工厂模式是最简单的设计模式之一,其实它并不属于Gof的23种设计模式,但应用也十分频繁,同时也是其余创建模式的基础,因此有必要先学习简单工厂模式。

在平时编程中,构建对象最常用的方式是 new 一个对象。乍一看这种做法没什么不好,而实际上这也属于一种硬编码。每 new 一个对象,相当于调用者多知道了一个类,增加了类与类之间的联系,不利于程序的松耦合。其实构建过程可以被封装起来,工厂模式便是用于封装对象的设计模式。

举个例子,直接 new 对象的方式相当于当我们需要一个苹果时,我们需要知道苹果的构造方法,需要一个梨子时,需要知道梨子的构造方法。更好的实现方式是有一个水果工厂,我们告诉工厂需要什么种类的水果,水果工厂将我们需要的水果制造出来给我们就可以了。这样我们就无需知道苹果、梨子是怎么种出来的,只用和水果工厂打交道即可。

事实上,将构建过程封装的好处不仅可以降低耦合,如果某个产品构造方法相当复杂,使用工厂模式可以大大减少代码重复

简单工厂基本实现流程

在这里插入图片描述

简单工厂定义

定义一个简单工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类
在这里插入图片描述

在这里插入图片描述

代码结构如下:

//抽象产品类AbstractProduct
class AbstractProduct
{
public://抽象方法:
};//具体产品类Basketball
class ConcreteProduct :public AbstractProduct
{
public://具体实现方法
};class Factory
{
public:AbstractProduct createProduct(string productName){AbstractProduct pro = NULL;if (productName == "ProductA"){pro = new ProductA();}else if (productName == "ProductB"){pro = new ProductB();}...}
};

客户端在使用时,只需要创建一个工厂对象,调用工厂对象的createProduct方法,并传入所需要的产品参数,即可得到所需产品实例对象,而无需关心产品的创建细节。

简单工厂模式代码实例

考虑有以下一个场景:
Jungle想要进行户外运动,它可以选择打篮球、踢足球或者玩排球。它需要凭票去体育保管室拿,票上写着一个具体球类运动的名字,比如“篮球”。体育保管室负责人根据票上的字提供相应的体育用品。然后Jungle就可以愉快地玩耍了。

我们采用简单工厂模式来实现上述场景。首先,体育保管室是工厂,篮球、足球和排球是具体的产品,而抽象产品可以定义为“运动球类产品SportProduct”.Jungle作为客户只需要提供具体产品名字,工厂就可“生产”出对应产品。

定义抽象产品类AbstractProduct,抽象方法不提供实现

//抽象产品类AbstractProduct
class AbstractSportProduct
{
public:AbstractSportProduct(){}//抽象方法:void printName(){};void play(){};
};

定义三个具体产品类

//具体产品类Basketball
class Basketball :public AbstractSportProduct
{
public:Basketball(){printName();play();}//具体实现方法void printName(){printf("Jungle get Basketball\n");}void play(){printf("Jungle play Basketball\n");}
};//具体产品类Football
class Football :public AbstractSportProduct
{
public:Football(){printName();play();}//具体实现方法void printName(){printf("Jungle get Football\n");}void play(){printf("Jungle play Football\n");}
};//具体产品类Volleyball
class Volleyball :public AbstractSportProduct
{
public:Volleyball(){printName();play();}//具体实现方法void printName(){printf("Jungle get Volleyball\n");}void play(){printf("Jungle play Volleyball\n");}
};

定义工厂类和工厂方法

class Factory
{
public:AbstractSportProduct *getSportProduct(string productName){AbstractSportProduct *pro = NULL;if (productName == "Basketball"){pro = new Basketball();}else if (productName == "Football"){pro = new Football();}else if (productName == "Volleyball"){pro = new Volleyball();}return pro;}
};

客户端使用方法示例

#include <iostream>
#include "SimpleFactory.h"int main()
{printf("简单工厂模式\n");//定义工厂类对象Factory *fac = new Factory();AbstractSportProduct *product = nullptr;product = fac->getSportProduct("Basketball");delete product;product = nullptr;product = fac->getSportProduct("Football");delete product;product = nullptr;product = fac->getSportProduct("Volleyball");	delete product;product = nullptr;system("pause");delete fac;fac = nullptr;return 0;
}

效果

在这里插入图片描述

可以看到,在客户端使用时,只需要提供产品名称作为参数,传入工厂的方法中,即可得到对应产品。抽象产品类中并没有提供公共方法的实现,而是在各个具体产品类中根据各自产品情况实现。

SimpleFactory.h

#ifndef __SIMPLE_FACTORY__
#define __SIMPLE_FACTORY__#include <iostream>
#include <string.h>
using namespace std;//抽象产品类AbstractProduct
class AbstractSportProduct {
public:AbstractSportProduct(){}virtual ~AbstractSportProduct(){}//抽象方法:// virtual void printName(){};// printName() 是一个纯虚函数,表示每个具体的产品(具体的运动产品)必须实现的接口方法。纯虚函数由 = 0 来标记,意味着该函数没有实现,必须由继承该类的子类来提供实现。virtual void printName() = 0;// virtual void play(){};virtual void play() = 0;
};//具体产品类Basketball
class Basketball :public AbstractSportProduct {
public:Basketball(){printName();play();}~Basketball() {}//具体实现方法void printName(){printf("Jungle get Basketball\n");}void play(){printf("Jungle play Basketball\n");}
};//具体产品类Football
class Football :public AbstractSportProduct {
public:Football(){printName();play();}~Football() {}//具体实现方法void printName(){printf("Jungle get Football\n");}void play(){printf("Jungle play Football\n");}
};//具体产品类Volleyball
class Volleyball :public AbstractSportProduct {
public:Volleyball(){printName();play();}~Volleyball() {		}//具体实现方法void printName(){printf("Jungle get Volleyball\n");}void play(){printf("Jungle play Volleyball\n");}
};class Factory {
public:std::shared_ptr<AbstractSportProduct> getSportProduct(string productName) {std::shared_ptr<AbstractSportProduct> pro;if(productName == "Basketball") {pro = std::shared_ptr<AbstractSportProduct>(new Basketball());} else if(productName == "Football"){pro = std::shared_ptr<AbstractSportProduct>(new Football());}else if (productName == "Volleyball"){pro = std::shared_ptr<AbstractSportProduct>(new Volleyball());}return pro;}
};#endif //__SIMPLE_FACTORY__

main.cpp

#include <iostream>
#include <memory>
#include "SimpleFactory.h"int main() {printf("简单工厂模式\n");//定义工厂类对象std::shared_ptr<Factory> fac = std::make_shared<Factory>();// std::shared_ptr<AbstractSportProduct> product = std::shared_ptr<AbstractSportProduct>(fac->getSportProduct("Basketball"));std::shared_ptr<AbstractSportProduct> product = fac->getSportProduct("Basketball");fac = std::make_shared<Factory>();product = fac->getSportProduct("Football");// product = std::shared_ptr<AbstractSportProduct>(fac->getSportProduct("Football"));fac = std::make_shared<Factory>();product = fac->getSportProduct("Volleyball");	// product = std::shared_ptr<AbstractSportProduct>(fac->getSportProduct("Volleyball"));	// 这段代码仅在 Windows 平台下执行。在 Windows 环境中,system("pause") 会暂停程序的执行,并在控制台输出 "Press any key to continue...",等待用户按任意键继续。这个代码片段在 Windows 下有用,但在其他操作系统中没有影响。
#ifdef win32system("pause");
#endif  return 0;
}

运行结果

在这里插入图片描述

在这里插入图片描述

简单工厂模式总结

在这里插入图片描述

在这里插入图片描述

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

http://www.xdnf.cn/news/16378.html

相关文章:

  • Hive【Hive架构及工作原理】
  • 如何高效通过3GPP官网查找资料
  • JAVA + 海康威视SDK + FFmpeg+ SRS 实现海康威视摄像头二次开发
  • 服务器托管:网站经常被攻击该怎么办?
  • 学习游戏制作记录(克隆技能)7.25
  • 秋招Day19 - 分布式 - 分布式锁
  • 初识决策树-理论部分
  • 肺癌预测模型实战案例
  • 【自动化运维神器Ansible】Ansible常用模块之Copy模块详解
  • 文件包含学习总结
  • 滑动窗口-7
  • 主要分布在背侧海马体(dHPC)CA1区域(dCA1)的时空联合细胞对NLP中的深层语义分析的积极影响和启示
  • ClickHouse 常用的使用场景
  • AWS WebRTC:我们的业务模式
  • [python][flask]flask蓝图使用方法
  • 【软件工程】构建软件合规防护网:双阶段检查机制的实践之道
  • Android studio自带的Android模拟器都是x86架构的吗,需要把arm架构的app翻译成x86指令?
  • FP16 和 BF16
  • 函数-变量的作用域和生命周期
  • 老题新解|奇偶数判断
  • 从Taro的Dialog.open出发,学习远程控制组件之【事件驱动】
  • OAuth 2.0 安全最佳实践 (RFC 9700) password 授权类型已经不推荐使用了,将在计划中移除
  • JS与Go:编程语言双星的碰撞与共生
  • vue2+node+express+MongoDB项目安装启动启动
  • go语言基础教程:【2】基础语法:基本数据类型(整形和浮点型)
  • js实现宫格布局图片放大交互动画
  • android app适配Android 15可以在Android studio自带的模拟器上进行吗,还是说必须在真机上进行
  • 无人机视觉模块技术解析
  • 【LeetCode Solutions】LeetCode 热题 100 题解(1 ~ 5)
  • [CSS]让overflow不用按shift可以滚轮水平滚动(纯CSS)