设计模式之简单工厂模式详解

简单工厂模式

工厂模式:工厂方法模式;

低阶:简单工厂模式;

高阶:抽象工厂模式;

1)概述

定义一个工厂类,根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。

在简单工厂模式中创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式。

2)流程

1.将需要创建的对象(Chart对象)的代码封装到不同的类中,称为具体产品类;

2.将公共的代码进行抽象和提取后封装在一个抽象产品类中,每一个具体产品类都是抽象产品类的子类;

3.提供一个工厂类用于创建各种产品,在工厂类中提供一个创建产品的工厂方法,该方法可以根据所传入的参数不同创建不同的具体产品对象;

4.客户端只需调用工厂类的工厂方法并传入相应的参数即可得到一个产品对象。

在这里插入图片描述

3)角色

● Factory(工厂角色):即工厂类,负责创建所有产品实例的内部逻辑;工厂类可以被外界直接调用,创建所需的产品对象;在工厂类中提供了静态的工厂方法 factoryMethod(),返回类型为抽象产品类型 Product。

● Product(抽象产品角色):是工厂类所创建的所有对象的父类,封装了各种产品对象的公有方法,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个通用的工厂方法,因为所有创建的具体产品对象都是其子类对象。

● ConcreteProduct(具体产品角色):是简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现在抽象产品中声明的抽象方法。

4)案例-初始方案

开发一套图表库,为应用系统提供不同外观的图表,例如柱状图、饼状图、折线图等,要求可以方便增加新类型的图表。

class Chart {private String type; //图表类型public Chart(Object[][] data, String type) {this.type = type;if (type.equalsIgnoreCase("histogram")) {//初始化柱状图}else if (type.equalsIgnoreCase("pie")) {//初始化饼状图}else if (type.equalsIgnoreCase("line")) {//初始化折线图}}public void display() {if (this.type.equalsIgnoreCase("histogram")) {//显示柱状图}else if (this.type.equalsIgnoreCase("pie")) {//显示饼状图}else if (this.type.equalsIgnoreCase("line")) {//显示折线图}	}
}

问题

(1) 在Chart类中包含很多“if…else…”代码块,整个类的代码冗长,阅读难度、维护难度和测试难度大,影响系统性能,程序在执行过程中需要做大量的条件判断。(2) Chart类的职责过重,它负责初始化和显示所有的图表对象,将各种图表对象的初始化代码和显示代码集中在一个类中实现,违反了“单一职责原则”,不利于类的重用和维护;而且将大量的对象初始化代码都写在构造函数中将导致构造函数非常庞大,对象在创建时需要进行条件判断,降低了对象创建的效率。(3) 当需要增加新类型的图表时,必须修改Chart类的源代码,违反了“开闭原则”。(4) 客户端只能通过new关键字来直接创建Chart对象,Chart类与客户端类耦合度较高,对象的创建和使用无法分离。(5) 客户端在创建Chart对象之前可能还需要进行大量初始化设置,例如设置柱状图的颜色、高度等,如果在Chart类的构造函数中没有提供一个默认设置,那就只能由客户端来完成初始设置,这些代码在每次创建Chart对象时都会出现,导致代码的重复。
5)案例-重构后

在这里插入图片描述

//抽象图表接口:抽象产品类
interface Chart {public void display();
}//柱状图类:具体产品类
class HistogramChart implements Chart {public HistogramChart() {System.out.println("创建柱状图!");}public void display() {System.out.println("显示柱状图!");}
}//饼状图类:具体产品类
class PieChart implements Chart {public PieChart() {System.out.println("创建饼状图!");}public void display() {System.out.println("显示饼状图!");}
}//折线图类:具体产品类
class LineChart implements Chart {public LineChart() {System.out.println("创建折线图!");}public void display() {System.out.println("显示折线图!");}
}//图表工厂类:工厂类
class ChartFactory {//静态工厂方法public static Chart getChart(String type) {Chart chart = null;if (type.equalsIgnoreCase("histogram")) {chart = new HistogramChart();System.out.println("初始化设置柱状图!");}else if (type.equalsIgnoreCase("pie")) {chart = new PieChart();System.out.println("初始化设置饼状图!");}else if (type.equalsIgnoreCase("line")) {chart = new LineChart();System.out.println("初始化设置折线图!");			}return chart;}
}// 客户端
class Client {public static void main(String args[]) {Chart chart;chart = ChartFactory.getChart("histogram"); //通过静态工厂方法创建产品chart.display();}
}
6)案例-使用配置文件优化

将静态工厂方法的参数存储在XML或properties格式的配置文件中。

<?xml version="1.0"?>
<config><chartType>histogram</chartType>
</config>

通过工具类 XMLUtil 读取配置文件中的字符串参数。

import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;public class XMLUtil {//从 XML 配置文件中提取图表类型,并返回类型名public static String getChartType() {try {//创建文档对象DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = dFactory.newDocumentBuilder();Document doc;							doc = builder.parse(new File("config.xml")); //获取包含图表类型的文本节点NodeList nl = doc.getElementsByTagName("chartType");Node classNode = nl.item(0).getFirstChild();String chartType = classNode.getNodeValue().trim();return chartType;}   catch(Exception e) {e.printStackTrace();return null;}}
}

引入配置文件和工具类XMLUtil后,客户端修改如下:

class Client {public static void main(String args[]) {Chart chart;String type = XMLUtil.getChartType(); //读取配置文件中的参数chart = ChartFactory.getChart(type); //创建产品对象chart.display();}
}
7)总结

简单工厂模式提供了工厂类用于创建对象,将对象的创建和对象的使用分开。

1.优点

实现了对象创建和使用的分离。

引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类。

2.缺点

工厂类集中了所有产品的创建逻辑,职责过重。

系统扩展困难,添加新产品需要修改工厂逻辑。

产品类型较多时,可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

简单工厂模式使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。

3.适用场景

工厂类负责创建的对象较少。

客户端只了解传入工厂类的参数,对于如何创建对象并不关心。

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

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

相关文章

Linux快速入门,上手开发 01.学习路线

少时曾许凌云志&#xff0c;当取世间第一流 再见少年拉满弓&#xff0c;不惧岁月不飓风 —— 24.3.20 1.Linux的发展历史 2.VM虚拟机的Linux初体验 3.图形化页面设置系统——快速上手 4.命令行操作——向专业前进 5.核心操作命令——必知必会&#xff08;管理企业级权限/定位b…

打印租赁行业现状与未来发展趋势分析

办公设备租赁行业现状与未来发展趋势分析 1. 简介 办公设备租赁行业是近年来快速发展的行业之一&#xff0c;随着数字化办公的普及和企业成本控制的需求增加&#xff0c;办公设备租赁市场呈现出了蓬勃的发展态势。本报告将对办公设备租赁行业的现状、发展历程以及未来发展趋势…

如何从零开始拆解uni-app开发的vue项目(二)

昨天书写了一篇如何从零开始uni-app开发的vue项目,今天准备写一篇处理界面元素动态加载的案例: 背景:有不同类别的设备,每个设备有每日检查项目、每周检查项目、每年检查项目,需要维保人员,根据不同设备和检查类别对检查项目进行处理,提交数据。 首先看一下界面: &l…

C++学习之旅(二)运行四个小项目 (Ubuntu使用Vscode)

如果是c语言学的比较好的同学 可以直接跟着代码敲一遍&#xff0c;代码附有详细语法介绍&#xff0c;不可错过 一&#xff0c;猜数字游戏 #include <iostream> #include <cstdlib> #include <ctime>int main() {srand(static_cast<unsigned int>(tim…

(一)基于IDEA的JAVA基础3

通过之前的内容&#xff0c;我们在建好的文件夹下建一个java文件&#xff0c;我们来在IDEA中写一下之前用记事本写的helloworld&#xff0c;我们先看一下java代码的规范: 1.java程序文件名一定要有意义&#xff0c;首字母一定要大写。 2.class后面的名字:由大小写字母&#x…

蓝队面试场景题,面试经验小记

答案不一定稳对&#xff0c;自己和别人讨论加查资料的。说话语速慢点&#xff0c;遇见不知道的就说没遇见过这种情况&#xff0c;但是遇见过类似情况举例子上报给高级人员&#xff08;有思路说思路&#xff09;。不知道的话统一说先隔离开&#xff0c;上杀毒软件&#xff0c;然…

Python字典的基本用法

Python字典是一种可变容器模型&#xff0c;能够存储任意类型对象&#xff0c;如字符串、数字、元组等。字典的每个键值对用冒号:分割&#xff0c;每个对之间用逗号,分割&#xff0c;整个字典包括在花括号{}中。这使得字典成为非常快速且易于使用的数据结构。 字典的特点 键的…

计算机网络相关

OSI七层模型 各层功能&#xff1a; TCP/IP四层模型 应用层 传输层 网络层 网络接口层 访问一个URL的全过程 在浏览器中输入指定网页的 URL。 浏览器通过 DNS 协议&#xff0c;获取域名对应的 IP 地址。 浏览器根据 IP 地址和端口号&#xff0c;向目标服务器发起一个 TCP…

「滚雪球学Java」:国际化(章节汇总)

&#x1f3c6;本文收录于「滚雪球学Java」专栏&#xff0c;专业攻坚指数级提升&#xff0c;助你一臂之力&#xff0c;带你早日登顶&#x1f680;&#xff0c;欢迎大家关注&&收藏&#xff01;持续更新中&#xff0c;up&#xff01;up&#xff01;up&#xff01;&#xf…

深度学习绘制热力图heatmap、使模型具有可解释性

思路 获取想要解释的那一层的特征图&#xff0c;然后根据特征图梯度计算出权重值&#xff0c;加在原图上面。 Demo 加上类激活(cam) 可以看到&#xff0c;cam将模型认为有利于分类的特征标注了出来。 下面以ResNet50为例: Trick: 使用 for i in model._modules.items():可以…

JavaScript和HTML/CSS之间有什么区别?它们之间的关系是什么?

下面是一个简单的代码示例&#xff0c;展示了HTML、CSS和JavaScript是如何一起工作的&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-w…

「Linux系列」Shell介绍及起步

文章目录 一、Shell简介二、Shell脚本三、Shell解释器四、相关链接 一、Shell简介 Shell本身是一个用C语言编写的程序&#xff0c;它既是一种命令语言&#xff0c;又是一种程序设计语言。作为命令语言&#xff0c;它交互式地解释和执行用户输入的命令&#xff1b;作为程序设计…

深度学习500问——Chapter03:深度学习基础(4)

文章目录 3.7 预训练与微调&#xff08;fine tuning&#xff09; 3.7.1 为什么无监督预训练可以帮助深度学习 3.7.2 什么是模型微调 fine tuning 3.7.3 微调时候网络参数是否更新 3.7.4 fine-tuning模型的三种状态 3.8 权重偏差和初始化 3.8.1 全都初始化为0 3.8.2 全都初始化为…

小程序调用相机拍照上传

用的wpy框架&#xff0c;有this&#xff0c;原声小程序就按照你们的调方法就行了 //打开相机openCream() {const _this this;wx.showActionSheet({itemList: ["拍照"],//[拍照,相册]itemColor: "",//成功时回调success: function(res) {if (!res.cancel) …

Android Launcher开发注意事项

在开发Android Launcher时&#xff0c;需要关注性能、用户体验、权限管理、兼容性等方面&#xff0c;同时遵循相关的开发者政策和最佳实践。有几个重要的注意事项&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎…

选择word中的表格VBA

打开开发工具 选择Visual Basic插入代码 Sub 选择word中的表格() Dim t As Table an MsgBox("即将选择选区内所有表格&#xff0c;若无选区&#xff0c;则选择全文表格。", vbYesNo, "提示") If an - 6 Then Exit Sub Set rg IIf(Selection.Type wdSel…

[HFCTF 2021 Final]easyflask

[HFCTF 2021 Final]easyflask [[python反序列化]] 首先题目给了提示&#xff0c;有文件读取漏洞&#xff0c;读取源码 #!/usr/bin/python3.6 import os import picklefrom base64 import b64decode from flask import Flask, request, render_template, sessionapp Flask(_…

HarmonyOS NEXT应用开发之侧滑返回事件拦截案例

介绍 在编辑场景中&#xff0c;存在用户误触返回&#xff0c;导致内容未保存就退出编辑页的现象; 本示例介绍使用NavDestination组件的onBackPressed回调对返回事件进行拦截&#xff0c;提示用户保存编辑内容&#xff0c;并使用preferences实例持久化保存内容。 效果预览图 使…

什么是常用的前端开发工具和框架?列举几个常用的前端框架和其特点。

前端开发工具和框架在Web开发中起着至关重要的作用&#xff0c;它们帮助开发者更高效地构建用户界面、管理数据和交互性。以下是一些常用的前端开发工具和框架&#xff1a; 1. **开发工具**&#xff1a; * **Visual Studio Code**&#xff1a;这是一个非常流行的代码编辑器…

使用verillog编写KMP字符串匹配算法

设计思路如下: 定义模块的输入输出信号:包括时钟信号clk、复位信号rst、模式串pattern、文本串text以及输出信号match。定义所需寄存器和变量:使用寄存器来存储状态机的状态以及其他控制变量,如模式串数组P、失配函数数组F、模式串位置p_index、文本串位置t_index等。在时钟…