设计模式 - 简单工厂模式

文章目录


前言

大家好,今天给大家介绍一下23种常见设计模式中的一种 - 工厂模式


1 . 问题引入

请用C++、Java、C#或 VB.NET任意一种面向对象语言实现一个计算器控制台程序,要求输入两个数和运算符 号,得到结果。

下面的代码实现默认认为两个操作数为Integer类型, 为了简单起见, 不引入泛型

2 . Version1

public class Version1 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.print("请输入数字A: ");int A = sc.nextInt();System.out.print("请输入你要执行的操作(+,-,*,/): ");String str = sc.next();System.out.print("请输入数字B: ");int B = sc.nextInt();if("+".equals(str)){System.out.println(A+B);}else if("-".equals(str)){System.out.println(A-B);}else if("*".equals(str)){System.out.println(A*B);}else if("/".equals(str)){System.out.println(A/B);}}
}

代码问题分析

上述代码对于初学者来说能写出来我想再正常不过了,哈哈, 我们来针对上述三点改进一下,命名还是按照A,B吧,毕竟又不是真的计算器。

3 . Version2 

public class Version2 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);try{System.out.print("请输入数字A: ");int A = sc.nextInt();System.out.print("请输入你要执行的操作(+,-,*,/): ");String str = sc.next();System.out.print("请输入数字B: ");int B = sc.nextInt();int ret = 0;switch (str){case "+":ret = A+B;break;case "-":ret = A-B;break;case "*":ret = A*B;break;case "/":if(B!=0) {ret = A/B;break;}else throw new RuntimeException("除数为0");default:throw new RuntimeException("没有该运算符!");}System.out.println("结果为: "+ret);}catch(Exception e){System.out.print("您的输入有误!: ");e.printStackTrace();}}
}

现在在看这段代码,是不是感觉没啥毛病了!  如果你没有学过面向对象编程,我没什么可说的,但是Java是面向对象编程的语言啊!  面向对象的三大特征是啥?

  1. 封装:封装是指将数据和行为(方法)封装在一个类中,并对外部隐藏对象的内部实现细节,只提供公共的访问方式。这样可以保护数据不被直接访问和修改,提高代码的安全性和可维护性。

  2. 继承:继承是指一个类(子类)可以继承另一个类(父类)的属性和方法,子类可以复用父类的代码,并且可以在不改变父类的情况下进行扩展和修改。通过继承可以建立类之间的层次关系,提高代码的可复用性和扩展性。

  3. 多态:多态是指同一个方法在不同的对象上有不同的行为表现。在面向对象编程中,多态可以通过继承和接口实现。多态性可以提高代码的灵活性和可扩展性,使代码更易于维护和扩展。

一个都没用到,哈哈,这肯定是不行的,还得再改进一下!

那么如何改进呢?  先来考虑封装, 是不是可以把操作逻辑和业务逻辑单独封装为一个类?

4. Version3

package FactoryModel.Option3;import java.util.Scanner;/*** 业务代码 和 计算代码实现分离! - 封装!*/
public class Version3 {public static void main(String[] args) {try(Scanner sc = new Scanner(System.in)){System.out.print("请输入数字A: ");int A = sc.nextInt();System.out.print("请输入你要执行的操作(+,-,*,/): ");String str = sc.next();System.out.print("请输入数字B: ");int B = sc.nextInt();if(B!=0) System.out.println(Operation.getResult(A,B,str));else throw new RuntimeException();}catch (Exception e){e.printStackTrace();}}
}/*** 孺鸟可教也,写得不错,这样就完全把业务和界面分离了。* 如果你现在要我写一个Windows应用程* 序的计算器,我就可以复用这个运算类(Operation)了*/
class Operation{public static int getResult(int A,int B, String oper){int ret = 0;switch (oper){case "+":ret = A+B;break;case "-":ret = A-B;break;case "*":ret = A*B;break;case "/":ret = A/B;}return ret;}
}
现在如果我希望增加一个开根(sqrt)运算,你如何改?
那只需要改Operation类就行了,在switch中加一个分支就行了
问题是你要加一个平方根运算,却需要让加减乘除的运算都得来参与编译,如果你一不小心,把加法运算改成了减法,这岂不是大大的糟糕。况且改代码这件事情不符合 开放 - 封闭原则

开放 - 封闭原则(Open-Closed Principle)是面向对象设计原则之一,提出者是Bertrand Meyer。该原则指出一个软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。换句话说,一个软件实体应该通过扩展来实现新功能,而不是通过修改已有的代码来实现。

具体来说,开放 - 封闭原则要求在系统需要变化时,应该通过添加新的代码来扩展功能,而不是修改已有的代码。这样可以保持系统的稳定性,减少对已有代码的影响,同时也更容易实现代码的复用和维护。

遵循开放 - 封闭原则可以使代码更加灵活、可扩展和可维护,同时也有利于降低系统的耦合度,提高代码的可复用性。这一原则在面向对象设计中扮演着重要的角色,帮助我们设计出更加稳定和易扩展的软件系统。

这个时候就该,继承登场了!

5 . Version4

public abstract class Operation {protected Integer A;protected Integer B;public Integer getA() {return A;}public void setA(Integer a) {A = a;}public Integer getB() {return B;}public void setB(Integer b) {B = b;}public abstract Integer getResult();
}
class OperationAdd extends Operation{@Overridepublic Integer getResult() {return A+B;}
}class OperationDiv extends Operation{@Overridepublic Integer getResult() {return A/B;}
}class OperationMul extends Operation{@Overridepublic Integer getResult() {return A*B;}
}class OperationSub extends Operation{@Overridepublic Integer getResult() {return A-B;}
}

这个时候如果我们再额外添加运算是不是就变得很简单了,只需要增加一个类,继承Operation即可!

6 . 简单工厂模式

简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,属于工厂模式的一种。在简单工厂模式中,有一个工厂类负责根据客户端的需求创建相应的产品对象,而客户端无需知道具体产品的创建细节,只需要通过工厂类来获取所需的产品对象。

/*** 简单工厂模式*/public class OperationFactory {public static Operation createOperate(String oper){Operation operation = null;try{switch (oper){case "+":operation = new OperationAdd(); // 多态break;case "-":operation = new OperationSub(); // 多态break;case "*":operation = new OperationMul(); // 多态break;case "/":operation = new OperationDiv(); // 多态break;default:throw new RuntimeException();}}catch(Exception e){e.printStackTrace();}return operation;}public static void main(String[] args) {Operation operate = OperationFactory.createOperate("+");operate.setA(10);operate.setB(20);System.out.println(operate.getResult());}
}

总结

以上就是这篇博客的主要内容了,大家多多理解,下一篇博客见!

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

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

相关文章

阿里云CentOS7安装Hadoop3伪分布式

ECS准备 开通阿里云ECS 略 控制台设置密码 连接ECS 远程连接工具连接阿里云ECS实例,这里远程连接工具使用xshell 根据提示接受密钥 根据提示写用户名和密码 用户名:root 密码:在控制台设置的密码 修改主机名 将主机名从localhost改为需要…

excel中批量插入分页符

excel中批量插入分页符,实现按班级打印学生名单。 1、把学生按照学号、班级排序好。 2、选择班级一列,点击数据-分类汇总。汇总方式选择计数,最后三个全部勾选。汇总结果一定要显示在数据的下发,如果显示在上方,后期…

操作教程|在MeterSphere中通过SSH登录服务器的两种方法

MeterSphere开源持续测试平台拥有非常强大的插件集成机制,用户可以通过插件实现平台能力的拓展,借助插件或脚本实现多种功能。在测试过程中,测试人员有时需要通过SSH协议登录至服务器,以获取某些配置文件和日志文件,或…

Python爬虫:爬虫常用伪装手段

目录 前言 一、设置User-Agent 二、设置Referer 三、使用代理IP 四、限制请求频率 总结 前言 随着互联网的快速发展,爬虫技术在网络数据采集方面发挥着重要的作用。然而,由于爬虫的使用可能会对被爬取的网站造成一定的压力,因此&#…

HarmonyOS实战开发-实现带有卡片的电影应用

介绍 本篇Codelab基于元服务卡片的能力,实现带有卡片的电影应用,介绍卡片的开发过程和生命周期实现。需要完成以下功能: 元服务卡片,用于在桌面上添加2x2或2x4规格元服务卡片。关系型数据库,用于创建、查询、添加、删…

SQL,group by分组后分别计算组内不同值的数量

SQL,group by分组后分别计算组内不同值的数量 如现有一张购物表shopping 先要求小明和小红分别买了多少笔和多少橡皮,形成以下格式 SELECT name,COUNT(*) FROM shopping GROUP BY name;SELECT name AS 姓名,SUM( CASE WHEN cargo 笔 THEN 1 ELSE 0 END)…

Prometheus +Grafana +node_exporter可视化监控Linux虚机

1、介绍 待补充 2、架构图 待补充 Prometheus :主要是负责存储、抓取、聚合、查询方面。 node_exporter :主要是负责采集物理机、中间件的信息。 3、搭建过程 配置要求:1台主服务器 n台从服务器 (被监控的linux虚机&am…

百度智能云千帆,产业创新新引擎

本文整理自 3 月 21 日百度副总裁谢广军的主题演讲《百度智能云千帆,产业创新新引擎》。 各位领导、来宾、媒体朋友们,大家上午好。很高兴今天在石景山首钢园,和大家一起沟通和探讨大模型的发展趋势,以及百度最近一段时间的思考和…

软件杯 深度学习+python+opencv实现动物识别 - 图像识别

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数:3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 inception_v3网络5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 *…

在Semantic Kernel中使用Qdrant向量数据库

本文将介绍如何在Semantic Kernel中使用Qdrant向量数据库,并演示如何在Semantic Kernel中进行向量更新和查询操作。 1. 背景 在前一篇文章《Qdrant 向量数据库的部署以及如何在 .NET 中使用 TLS 安全访问》中,我们介绍了如何使用 Docker 部署 Qdrant 向…

RestTemplate 请求响应数据出现乱码问题,RestTemplate 如何解压缩 gzip 数据

文章目录 1.问题描述2.问题分析3.问题解决3.1 Apache HttpClient 依赖3.2 RestTemplate 配置类3.3 测试 1.问题描述 直接通过浏览器访问请求没有问题,但是通过 RestTemplate 访问请求却会出现乱码问题。 2.问题分析 首先我认为是 SpringBoot 版本、JDK 版本、项目结…

jmockit-01-test 之 jmockit 入门使用案例

拓展阅读 jmockit-01-jmockit 入门使用案例 jmockit-02-概览 jmockit-03-Mocking 模拟 jmockit-04-Faking 伪造 jmockit-05-代码覆盖率 mockito-01-入门介绍 mockito-02-springaop 整合遇到的问题,失效 jmockit 说明 jmockit 可以提供基于 mock 的测试能力…

【黑马头条】-day04自媒体文章审核-阿里云接口-敏感词分析DFA-图像识别OCR-异步调用MQ

文章目录 day4学习内容自媒体文章自动审核今日内容 1 自媒体文章自动审核1.1 审核流程1.2 内容安全第三方接口1.3 引入阿里云内容安全接口1.3.1 添加依赖1.3.2 导入aliyun模块1.3.3 注入Bean测试 2 app端文章保存接口2.1 表结构说明2.2 分布式id2.2.1 分布式id-技术选型2.2.2 雪…

【TB作品】MSP430G2553,超声波倒车雷达PCB,单片机,超声波SR04,键盘,oled,

题目 硬件:MSP430G2553、 SR04超声波传感器 、3*4键盘、 无源蜂鸣器、oled显示屏 软件 1 、实时显示测量得到的距离 2、按键设置一个报警门限数值,直接输入数值后确认 3、低于报警门限数值就开始报警,而且距离越近蜂鸣器的鸣叫频率越高 程序…

uniapp 微信小程序 canvas 手写板获取书写内容区域并输出

uni.canvasGetImageData 返回一个数组,用来描述 canvas 区域隐含的像素数据,在自定义组件下,第二个参数传入自定义组件实例 this,以操作组件内 组件。 // 获取目标 canvas 的像素信息 pixelData let canvas uni.createSelector…

追踪Aurora(欧若拉)勒索病毒,Emsisoft更新解密工具

Aurora(欧若拉)勒索病毒首次出现于2018年7月左右,加密后的文件后缀为Aurora,2018年11月,此勒索病毒的一款变种样本,加密后的文件后缀为Zorro,同时发现了此勒索病毒的一个BTC钱包地址: 18sj1xr86c3YHK44Mj2…

Day54:WEB攻防-XSS跨站Cookie盗取表单劫持网络钓鱼溯源分析项目平台框架

目录 XSS跨站-攻击利用-凭据盗取 XSS跨站-攻击利用-数据提交 XSS跨站-攻击利用-flash钓鱼 XSS跨站-攻击利用-溯源综合 知识点: 1、XSS跨站-攻击利用-凭据盗取 2、XSS跨站-攻击利用-数据提交 3、XSS跨站-攻击利用-网络钓鱼 4、XSS跨站-攻击利用-溯源综合 漏洞原理…

蓝桥杯 java 凑算式 16年省赛Java组真题

题目 思路: 求有多少种解法 比如:68/3952/714就是一种解法,53/1972/486 是另一种解法 8/3952/714是可以除尽的 但是后面一个不行 所以我们也要通分 代码: public class 凑算式 {static int[] a {1, 2, 3, 4, 5, 6, 7, 8, 9};static int c…

力扣热门算法题 135. 分发糖果,146. LRU 缓存,148. 排序链表

135. 分发糖果,146. LRU 缓存,148. 排序链表,每题做详细思路梳理,配套Python&Java双语代码, 2024.03.28 可通过leetcode所有测试用例。 目录 135. 分发糖果 解题思路 完整代码 Python Java 146. LRU 缓存 …

Web系统开发之——文章管理

原文地址:Web系统开发之——文章管理 - Pleasure的博客 下面是正文内容: 前言 经过一番考量,关于Web应用系统功能部分的开发,决定采取基础的文字文章管理为核心功能。 不再采取前后端分阶段完成的方式,而是以一个一个…