【设计模式】简单工厂模式

news2024/9/21 10:45:24

简单工厂模式–》工厂模式—》抽象工厂模式

文章目录

  • 简单工厂模式定义:
  • 各个角色
    • 1. 抽象产品类
    • 2. 具体产品类:
    • 3. 工厂类:简单工厂模式的核心。
    • 客户端
  • 设计图表
    • 未使用简单工厂模式:
    • 出现的问题:
    • 使用简单工厂模式:
      • 抽象产品类
      • 具体产品类
      • 静态工厂方法
  • 总结:
    • 优点:
    • 缺点:
    • 使用场景:
    • 改进:

简单工厂模式定义:

简单工厂模式:定义一个工厂类,它可以根据参数的不同返回不同的实例,被创建的实例通常都有共同的父类,因为在简单工厂模式中用于创建实例的方法是今天方法,因此简单工厂模式也称为静态工厂模式,它属于类创建型模式。

1.要点
当你需要什么,只需要传入一个正确的参数,就可以获取所需要的对象,而无需知道细节,简单工厂的结构模式比较简单,其核心就是工厂类的设计。

各个角色

1.Factory(工厂角色):工厂角色即工厂类,它是简单工厂模式的核心,负责实现创建所有产品实例的内部逻辑,工厂类可以被外界直接调用,创建所需的产品对象,
在工厂中提供静态的工厂方法factory(),它的返回类型为抽象产品类型Product。)
2.Product(抽象产品角色):它是工厂类所创建的所有对象的父类,封装了各种产品对象的公有方法,它的引入提高了系统的灵活性,是的工厂类只需要定义一种通用的工厂方法,因为所有擦黄建德具体铲平都是它的子类对象。
3.ConcreteProduct(具体产品角色):简单工厂模式的创建目标,所有被创建的对象都充当这个角色的具体类的实例,每个具体产品角色都继承了抽象产品角色,需要实现的抽象产品中声明的抽象方法。
请添加图片描述

代码实现 :

1. 抽象产品类

在使用简单工厂模式时,首先需要对产品进行重构,不能设计一个包罗万象的产品类,而根据实际情况设计一个铲平层次结构,将所有产品公共的代码移到抽象产品类,并在抽象产品类中声明一些抽象方法,以供不同的具体产品来实现,如下:

class Product
{
   //所有产品类的公共业务方法
}
public:
  void methodSame()
  {
      //公共方法的实现。
  }
  //声明抽象业务方法
  virtual void methoddiff() = 0;
  };
  

2. 具体产品类:

实现抽象类中的抽象方法。

class ConcreateProductA:public Product
{
   //实现业务
   public:
      void methodiff()
      {
          //业务方法的具体实现。
      }
}class ConcreateProductB:public Product
{
   //实现业务
   public:
      void methodiff()
      {
          //业务方法的具体实现。
      }
}

3. 工厂类:简单工厂模式的核心。

提供的工厂方法必须是,静态方法>
功能:通过客户端传入的参数,选择创建不同的对象。

class Factory
{
   public:
   static Product * getProduct(string src)
   {
      Product *product = NULL;
      if(src = "B")
      {
      product = new ConcreteProductA();
      //初始化 product
       }
       else if(src = B)
       {
          product = new ConcreteProductB();
           //初始化产品
       }
       return product;
   }
};

客户端

int main()
{
   Profuct *product = nullptr;
   //通过工厂创建产品对象
   product = Factory::getProduct("A");
   product -> methodSame();
   product->methodDiff();
}

设计图表

未使用简单工厂模式:

class Chart
{
private:
	string type; // 图表类型
public:
	Chart(const string& t) : type(t)
	{
		if (type == "histogram") {
			// 初始化柱状图
		}
		else if (type == "pie") {
			// 初始化饼状图
		}
		else if (type == "line") {
			// 初始化折线图
		}
	}

	void display()
	{
		if (type == "histogram") {
			// 显示柱状图
		}
		else if (type == "pie") {
			// 显示饼状图
		}
		else if (type == "line") {
			// 显示折线图
		}
	}
};

出现的问题:

  1. 在Chart类中包含很多"if…else"代码块,整个类的代码相当冗长;如果需求大,代码会越长,阅读难度和维护难度越大;而且大量条件语句会影响系统的性能。
  2. Chart类的职责过重,违反了“单一职责原则”,不利于类的重用和维护。
  3. 当需要增加新类型的图表时,必须修改chart类的源代码,违反了“开闭原则”。
  4. 客户端只能通过new关键字来直接创建Chart类对象,4.类与客户端类的耦合度较高,对象的创建和使用无法分离。

使用简单工厂模式:

抽象产品类

class Chart
{
public:
    virtual void display() = 0;
};

具体产品类

//具体产品类
class histogram : public Chart
{
public:
     histogram()
    {
        cout << "创建柱状图" << endl;
    }
    void display()
    {
        cout << "显示柱状图" << endl;
    }
};
class Linechart : public Chart
{
public:
    Linechart()
    {
        cout << "创建线形图" << endl;
    }
    void display()
    {
        cout << "显示线形图" << endl;
    }
};

静态工厂方法

1. 没有this指针,不依赖于对象,只能访问静态成员。
2. 可以直接根据类来调用。因为它的功能就是创建对象。
class Factory
{
public:
    //静态工厂方法   
    //没有this指针,不依赖于对象,只能访问静态成员。
    //可以直接根据类来调用。因为它的功能就是创建对象。
    static Chart *getFactory(string src)
    {
       Chart * chart = NULL;
        if (src == "histogram")
        {
            chart = new histogram();
            cout << "初始化柱状图" << endl;
        }
        else if (src == "line")
        {
            chart = new Linechart();
            cout << "初始化线形图" << endl;
        }
        return chart;
    }
};
int main()
{
    Chart *fa = NULL;
    //通过静态工厂方法创建具体产品类对象
    fa = Factory::getFactory("line");
    fa->display();
}

结果:请添加图片描述

总结:

在简单工厂模式下,客户端通过工厂类创建了一个产品类的实例,而无需直接使用new关键字来创建对象。

优点:

1.工厂类包含必要的逻辑判断,可以再什么时候创建哪一个产品的实例。客户端就不需要做这些了。
2.客户端无需知道具体产品类的类名,只需要直到具体产品类对应的参数,对于一些复杂的类名,免去了使用者去记忆。
3.引入配置文件,可以在不修改任何客户端代码的情况下更换合增加新的具体产品类,提高了系统的灵活性。

缺点:

1.工厂类集中类所有产品的创建逻辑,职责过重。
2.使用简单工厂模式势必增加系统中累的个数。增加了系统的复杂度。
3.系统扩展困难,因为每添加一个具体的产品类,势必要修改工厂类。产品太多,更难维护,
4.简单工厂模式使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。

使用场景:

1.工厂类负责创建的对象少。
2.客户端只知道传入工厂类的参数,对如何创建不关注,

改进:

class Chart
{
public:
    virtual void display() = 0;
     static Chart *getFactory(const string &src);
};
 static Chart *Chart::getFactory(const string &src)
    {
       Chart * chart = NULL;
        if (src == "histogram")
        {
            chart = new histogram();
            cout << "初始化柱状图" << endl;
        }
        else if (src == "line")
        {
            chart = new Linechart();
            cout << "初始化线形图" << endl;
        }
        return chart;
    }

还可以使用Json,通过修改配置文件来创建不同的对象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1995.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小熊派-FreeRTOS-点灯学习过程-20221029

一、前言准备 1、小熊派一个&#xff08;STM32L431RCT6&#xff09; 2、STM32CubeMX 3、keil5 4、小熊派的配套开发资料&#xff08;用于出问题的时候替换&#xff09; 二、实现过程 代码主要由STM32CubeMX生成&#xff0c;所以过程主要是配置CubeMX. 1、芯片选型 STM3…

用 Pyinstaller 模块将 Python 程序打包成 exe 文件(全网最全面最详细)

目录 打包前置知识 一、什么是exe可执行文件&#xff1f; 二、为什么要将 Python 程序打包为 exe 可执行文件&#xff1f; 三、为什么 Python 程序不能直接运行呢&#xff1f; 四、我们用什么来打包 Python 文件呢&#xff1f; 五、打包有哪几种分类呢&#xff1f; 打包…

【ArcGIS微课1000例】0041:ArcGIS利用坐标生成点的方法总结

本文讲解ArcGIS利用坐标生成点的3种方法。 文章目录 一、转到XY工具定位二、输入绝对XY生成点三、添加XY数据一、转到XY工具定位 这样确实可以在图上快速定位某个经纬度的点,但是生成的对象是“注记类”要素,即不是地理实体,而仅仅是为了绘图表现的东西。可以用如下工具来控…

Kotlin协程-并发处理-基础

一、协程与并发 Kotlin协程是基于线程执行的。经过一层封装以后&#xff0c;Kotlin协程面对并发&#xff0c;处理方式与Java不同。 在java的世界里&#xff0c;并发往往是多个线程一起工作&#xff0c;存在共享的变量。需要处理好同步问题。要避免把协程与线程的概念混淆。 …

验证码的编写

编写一个验证码(可以通过键盘输入需要获取验证码的位数)&#xff1a; public class IdentifyingCode {public static void main(String[] args) {//验证码的编写IdentifyingCode identifyingCode new IdentifyingCode();//扫描键盘输入Scanner scanner new Scanner(System.i…

【数据结构基础】之数组介绍,生动形象,通俗易懂,算法入门必看

【数据结构基础】数组前言一、数组的定义1.基本概念和内存图2.数组的性质3.数据结构二、玩转数组1.循环遍历打印数组的每一个值2.查找一个数组里存在的值3.打擂台的形式找最大值4.元素的位移5.数组的扩容6.数组的反转三、二维数组四、初识算法1.排序算法2.查找算法3.算法性能4.…

电力电子的一些知识

文章目录数电模电逻辑电路与或非异或 门电路与的物理电路边沿触发器功率交流容量直流容量桥电路CHBDABTHD电路器件LM7815与LM7915数电模电 逻辑电路 与或非异或 门电路 与乘大于1或加大于1异或异性为1&#xff0c;异吗&#xff1f; 与的物理电路 当二极管是高电平&#xf…

stm32f407探索者开发板(一)——资源介绍(顺便说下无人机的进度状况)

文章目录零、前言一、前置问题二、注意事项三、学习方法四、外观五、关于sw仿真零、前言 最近虽然在做无人机小项目啦&#xff0c;但是呢由于疫情&#xff0c;各种零件一直没发&#xff0c;很头疼&#xff0c;现在关于遥控器和接收机的选型也没定下来&#xff0c;嗯&#xff0…

【Java】Spring boot快速上手(一):葵花宝典

目录前言学习目标学习内容工具及其环境配置说明新建spring web项目打开idea 新建项目创建项目配置设置静态资源映射编写html访问前端最后前言 该系列文章仅用于个人学习记录&#xff0c;适合入门级&#xff0c;对于文中有错误的地方还望海涵&#xff0c;之前打算结合《瑞吉外卖…

【JavaSE】初识Java

文章目录一. Java语言概述1. Java语言的组成1.1 什么是JavaSE1.2 什么是JavaEE1.3 什么是JavaME2. Java语言的产生3. Java语言的优势二. 初识Java的main方法1. main方法示例2. 运行Java程序一. Java语言概述 Java是一门面向对象编程语言&#xff0c;不仅吸收了C语言的各种优点…

学习python第一天,请教一下怎么学?

前言 小白建议以视频入门&#xff0c;或者是看一些适合入门的书比如《笨办法学Python》&#xff1b; 在这个资源泛滥的时代&#xff0c;更需要有自己的一套学习方法。尤其是针对自学来说&#xff0c;遇到问题不知道如何解决&#xff0c;那么就要做好前置的学习计划&#xff1…

我越努力生活,生活就越努力的干我

92年出生&#xff0c;工作9年。我也不知道今年多少岁了&#xff0c;结婚6年&#xff0c;两个小孩&#xff0c;一个是男孩&#xff0c;「该死的」另一个也是男孩&#xff0c;周五晚上&#xff0c;手机屏幕的时间刚过9点50&#xff0c;我小心拉开门缝往里面瞧了一眼后推开房门&am…

C++ Reference: Standard C++ Library reference: C Library: cstring: strchr

C官网参考链接&#xff1a;https://cplusplus.com/reference/cstring/strchr/ 函数 <cstring> strchr const char * strchr ( const char * str, int character ); char * strchr ( char * str, int character ); 定位字符串中第一个出现的字符 返回指向C字符串s…

[前端基础] 浏览器篇

提供基础用法&#xff0c;基础概念引用 MDN、W3C&#xff0c;基础内容做扩展知识&#xff0c;可应对面试&#xff0c;详细原理及应用需要去官网、GitHub 深入学习。 1、常用 BOM 方法 BOM&#xff08;browser object model&#xff09;简称浏览器对象模型&#xff0c;BOM 提供…

【SpringBoot笔记18】SpringBoot实现统一异常处理、统一结果响应、统一参数校验

这篇文章&#xff0c;主要介绍如何利用SpringBoot框架实现统一异常处理、统一结果响应、统一参数校验。 目录 一、SpringBoot统一结果响应 1.1、创建工程 1.2、配置FastJson 1.3、创建ResultEnum枚举 1.4、创建Result实体类 二、SpringBoot统一异常处理 2.1、创建自定义…

【LeetCode 784. 字母大小写全排列】异或进行字母大小写变换

LeetCode784.字母大小写全排列解题方法&#xff1a;回溯用异或进行大小写变换正式解题总代码784.字母大小写全排列 给定一个字符串 s &#xff0c;通过将字符串 s 中的每个字母转变大小写&#xff0c;我们可以获得一个新的字符串。 返回 所有可能得到的字符串集合 。以 任意顺…

htm+JS实现绘制数学函数绘图

htmJS实现绘制数学函数绘图 其中常用的函数可参见&#xff0c;JS中常用的Math方法 https://blog.51cto.com/u_10725738/5253407 https://www.jb51.net/article/9151.htm JS(JavaScript)常用Math函数与用法说明 方法描述示例abs(x)返回数的绝对值。Math.abs(-10)//返回10aco…

【Linux】--谈谈冯诺依曼体系结构和操作系统

文章目录冯诺依曼体系组成部分数据层面CPU存储器外设结论操作系统什么是操作系统为什么要有操作系统怎么去管理总结冯诺依曼体系 冯诺依曼结构是一种将程序指令存储器和数据存储器合并在一起的存储器结构&#xff0c;数学家冯诺依曼提出了计算机制造的三个基本原则&#xff0c…

C++继承、多继承及菱形继承

继承 继承是C面向对象的三大特性之一&#xff08;封装、继承和多态&#xff09;。 一、构造和析构顺序 先执行父类构造函数&#xff0c;再执行子类构造函数&#xff1b; 先执行子类析构函数&#xff0c;在执行父类析构函数。 二、同名隐藏 2.1 概念 子类中的同名属性和成…

vue父子组件传值记录

之前父子组件传值不太熟悉&#xff0c;组件间传值要么用vuex&#xff0c;要么用sessionStorage缓存&#xff0c;但是sessionStorage感觉用多了不太好&#xff0c;缓存太多容易混淆&#xff0c;vuex还是比较好用&#xff0c;&#xff0c;但是用的过程中好像有个问题&#xff0c;…