设计模式——工厂三兄弟之简单工厂

news2024/11/15 20:50:37

1.业务需求

​ 大家好,我是菠菜。在介绍这期简单工厂设计模式前,我们先来看看这样的需求:制作一个简单的计算器,能够实现控制台输入俩个数以及运算符完成运算
计算器

2.初步实现

实现第一版思路:

​ 创建计算器类,控制台输入俩个数以及运算符,通过if条件输出运算结果。

CalClient 类:

public class CalClient {
    public static void main(String[] args) {

        Scanner sc=new Scanner(System.in);
        System.out.println("请输入第一个数:");
        double numbera=sc.nextDouble();
        System.out.println("请输入运算符:");
        String operator=sc.next();
        System.out.println("请输入第二个数:");
        double numberb=sc.nextDouble();
        
        if("+".equals(operator)){
            System.out.println("运算结果为:"+(numbera+numberb));
        }else  if("-".equals(operator)){
            System.out.println("运算结果为:"+(numbera-numberb));
        }else  if("*".equals(operator)){
            System.out.println("运算结果为:"+(numbera*numberb));
        }else  if("/".equals(operator)){
            if(numberb==0){
                System.out.println("除数不能为零");
                return;
            }
            System.out.println("运算结果为:"+(numbera/numberb));
        }
    }
}

思考:这段代码在当时初学编程来说,没有问题,而且结果都能执行成功并输出。但是现在我们再来看是不是有点不太满意的地方,比如:计算控制台逻辑和计算方法逻辑耦合在一起,不满足上一期我们所学的单一职责原则,于是我又优化了一版。

实现第二版思路:

​ 增加Operation运算类,将计算方法封装到里面,把计算控制台逻辑和计算方法拆开,降低耦合。

Operation类:

public class Operation {

    public static Double getOperationResult(double numbera,double numberb,String operator){
        Double result=null;

        switch (operator){
            case "+":
                result=numbera+numberb;
                break;
            case "-":
                result=numbera-numberb;
                break;
            case "*":
                result=numbera*numberb;
                break;
            case "/":
                if(numberb==0){
                    System.out.println("除数不能为零");
                    return result;
                }
                result=numbera/numberb;
                break;
        }

        return result;
    }
}

CalClient类:

public class CalClient {
    public static void main(String[] args) {

        Scanner sc=new Scanner(System.in);
        System.out.println("请输入第一个数:");
        double numbera=sc.nextDouble();
        System.out.println("请输入运算符:");
        String operator=sc.next();
        System.out.println("请输入第二个数:");
        double numberb=sc.nextDouble();

    //2.将业务逻辑和界面逻辑分开 解耦
    System.out.println("运算结果为:"+(Operation.getOperationResult(numbera,numberb,operator)));
    }
}

​ **思考:**上述代码,虽然将控制台和计算方法解耦,而且这个计算方法类可以做到一定程度上的复用,但是又有了一些新的问题:后续添加或修改计算方法要修改整个Operation类并编译,不安全而且会影响到正常运行的代码,而且该设计没有面向对象编程。我思考了一下,于是就有了下一个升级版本。

3.方案改进

实现第三版本思路:

​ 增加类OperationFactory,用于实例化具体的计算实例。增加抽象类AOpeartion,提取统一计算方法。增加计算实现类OperationAdd、OperationSub、OperationMul、OperationDiv。

计算器简单工厂模式

OperationFactory类:

public class OperationFactory {

    public static AOpeartion createOperation(String operator){
        AOpeartion opeartion=null;
        switch (operator){
            case "+":
                opeartion=new OperationAdd();
                break;
            case "-":
                opeartion=new OperationSub();
                break;
            case "*":
                opeartion=new OperationMul();
                break;
            case "/":
                opeartion=new OperationDiv();
                break;
        }

        return opeartion;
    }
}

AOpeartion类:

public abstract class AOpeartion {
    public abstract Double getOperationResult(double numbera, double numberb);
}

OperationAdd类:

public class OperationAdd extends AOpeartion {
    @Override
    public Double getOperationResult(double numbera, double numberb) {
        return numbera+numberb;
    }
}

OperationSub类:

public class OperationSub extends AOpeartion {
    @Override
    public Double getOperationResult(double numbera, double numberb) {
        return numbera-numberb;
    }
}

OperationMul类:

public class OperationMul extends AOpeartion {
    @Override
    public Double getOperationResult(double numbera, double numberb) {
        return numbera*numberb;
    }
}

OperationDiv类:

public class OperationDiv extends AOpeartion {
    @Override
    public Double getOperationResult(double numbera, double numberb) {
        if(numberb==0){
            System.out.println("除数不能为零");
            return null;
        }
        return numbera/numberb;
    }
}

CalClient类:

public class CalClient {
    public static void main(String[] args) {

        Scanner sc=new Scanner(System.in);
        System.out.println("请输入第一个数:");
        double numbera=sc.nextDouble();
        System.out.println("请输入运算符:");
        String operator=sc.next();
        System.out.println("请输入第二个数:");
        double numberb=sc.nextDouble();

     //3.利用简单工厂实现 易维护 易复用 易拓展
        AOpeartion opeartion=OperationFactory.createOperation(operator);
        if(null!=opeartion){
            System.out.println("运算结果为:"+(opeartion.getOperationResult(numbera,numberb)));
        }else{
            System.out.println("运算工厂获取运算类失败");

        }

    }
}

​ 思考:OperationFactory工厂类通过输入的运算符去实例化相应合适的对象,通过多态返回父类的方式实现了计算器的结果。后续如果修改具体的计算方法只要修改具体的计算类即可,不会影响其它计算类。如果增加计算方法,增加实现相应的计算类的具体子类以及增加计算工厂类的switch分支即可。

4.定义和组成结构

​ 工厂模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。按实际业务场景划分,工厂模式有 3 种不同的实现方式,分别是简单工厂模式、工厂方法模式和抽象工厂模式。我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”。在简单工厂模式中创建实例的方法通常为静态(static)方法,因此简单工厂模式(Simple Factory Pattern)又叫作静态工厂方法模式(Static Factory Method Pattern)。

简单工厂模式的主要角色如下:

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

简单工厂模式

5.优缺点以及应用场景

优点:

  • 简单工厂模式实现了对象创建和使用的分离,职责分明
  • 客户端无需知道所创建具体对象的类名,只需知道参数即可

缺点:

  • 工厂类集中了所有产品的创建逻辑,职责过重
  • 系统扩展困难,添加新产品要修改原有逻辑,违反了开闭原则,产品种类一多,工厂类逻辑过于复杂,不利有扩展和维护

应用场景: 对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。

友情提示:请尊重作者劳动成果,如需转载本博客文章请注明出处!谢谢合作!
【作者:我爱吃菠菜 个人博客地址

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

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

相关文章

k8s污点及容忍度+实践

k8s污点及容忍度实践 前言 一、标签、注解和污点1、如何查询污点及一个容器或者工作负载的标签注解a、通过describe命令查看一个节点的详细信息 2、标签查询修改 二、污点和容忍度容忍度(Tolerations)2、taint / label命令及解释 三、为应用程序设置干扰…

NameSilo + Cloudflare 给网站加个域名(附 NameSilo 购买域名优惠码)

网站做好了之后,下一步就是买域名 在国内买域名的话,还需要备案,个人名下备案好像是还有限制,我就去 NameSilo 上面买的 在买之前,对比过几家 比如: godaddy/namecheap/cloudflare 本来是倾向于在 godaddy 上面买的,因为它支持支付宝支付,但是在详细看的时候,发现如果购买一年…

腾讯云COS上传文件出现的问题

1、没有配置 ObjectMetadata 的文件长度 腾讯云COS上传文件出现数据损坏问题_no content length specified for stream data. strea-CSDN博客 2、 使用 FileInputStream使用完没有及时关闭导致报错 ClientAbortException: java.nio.channels.ClosedChannelException 添加…

AI Agent:自主性、反应性与交互性的融合,将颠覆软件行业

Agent来袭:AI如何变身软件界的超级英雄? ©作者|Zhongmei 来源|神州问学 前言 “AI Agent不仅会彻底改变计算机的使用方式,它还将颠覆软件行业,是一个对科技行业的冲击波,是一场自‘输入命令到点击图标’变革之后…

266 基于matlab的FCM+KFCM模糊C均值聚类分析算法

基于matlab的FCMKFCM模糊C均值聚类分析算法,输入分割对象,对分割对象进行参数设置,包括分割类别数,核参数。输出分割结果。具有GUI操作界面。程序已调通,可直接运行。 266 FCM KFCM 模糊C均值聚类 GUI - 小红书 (xiaoh…

站内信设计

参考文章:https://cloud.tencent.com/developer/article/1684449 b站站内信业务设计: 消息的类型分为: 1、系统消息 2、、点赞、回复等用户行为之间的消息(事件提醒) 3、用户之间的消息 系统消息 用一个用户消息表可以吗? 可…

主副坐标轴作图(即双坐标轴)

主副坐标轴显示: import numpy as np from matplotlib import pyplot as plt plt.rcParams[font.sans-serif][SimHei] plt.rcParams[axes.unicode_minus] False xnp.arange(0.1,10,0.01) data1np.exp(x) data2np.log(x) fig,ax1plt.subplots() #subplots一定要带s…

室内也可以用北斗定位?还能用RTK?

室内卫星顾名思义,就是在室内有遮挡环境中的卫星定位技术,众所周知,目前全球几大GNSS定位系统已经很完善,但是GNSS有个致命的弱点,就是地面如果有遮挡就没有信号,在这样的条件下,在室内定位场景…

YOLOv8+PyQt5农作物杂草检测系统完整资源集合(yolov8模型,从图像、视频和摄像头三种路径识别检测,包含登陆页面、注册页面和检测页面)

农作物杂草检测YOLOV8(https://mbd.pub/o/bread/mbd-ZpaTl5tv)_哔哩哔哩_bilibili 资源包含可视化的农作物杂草检测系统,基于最新的YOLOv8训练的农作物杂草检测模型,和基于PyQt5制作的可视化农作物杂草检测系统,包含登陆页面、注册页面和检测…

免费,Python蓝桥杯等级考试真题--第15级(含答案解析和代码)

Python蓝桥杯等级考试真题–第15级 一、 选择题 答案:B 答案:D 解析:集合的并集运算有两种方式,一种是使用“|”运算符进行操作,另一种是使用union()方法来实现,故答案为D。 答案:A 解析&…

STM32启动过程分析

Keil堆栈设置注意事项 一、启动模式 复位方式:上电复位、硬件复位、软件复位 从地址0x0000 0000处取出堆栈指针MSP的初始值,该值就是栈顶地址。从地址0x0000 0004处取出程序计数器指针PC的初始值,该值指向复位后执行的第一条指令。 说白了就…

2024年【危险化学品经营单位安全管理人员】考试报名及危险化学品经营单位安全管理人员找解析

题库来源:安全生产模拟考试一点通公众号小程序 危险化学品经营单位安全管理人员考试报名考前必练!安全生产模拟考试一点通每个月更新危险化学品经营单位安全管理人员找解析题目及答案!多做几遍,其实通过危险化学品经营单位安全管…

ArcGIS基本操作-常用的空间分析工具梳理

ArcGIS空间分析工具使用 如果我们在进行科研时需要将研究区地形地貌作为一项指标的话,将可能遇到坡度、坡向、地形起伏度、地表切割深度等因子计算,下面我向大家介绍如何利于ArcGIS软件的空间分析工具,基于高程数据,分析重庆市的…

聊聊如何感知项目引入哪些功能特性

前言 使用过springcloud全家桶朋友,应该知道springcloud涉及的组件很多,为了让开发者快速了解项目引入了springcloud哪些组件,springcloud引入了HasFeatures,配合Actuator,可以让开发者感知到项目引入的组件功能类型、…

深度解析Nginx配置文件:从全局块到upstream块的探索之旅

Nginx配置文件的简介 在浩瀚的互联网世界中,Nginx就如同一座大型交通枢纽,将访问者的请求精准地引导到正确的服务终点。而这一切,都离不开一个神秘而重要的角色——Nginx配置文件。这个文件,就像是一份详尽的路线图,为…

leetCode.84. 柱状图中最大的矩形

leetCode.84. 柱状图中最大的矩形 题目思路 代码 class Solution { public:int largestRectangleArea( vector<int>& h ) {int n h.size();vector<int> left( n ), right( n );stack<int> st;// 求每个矩形的第一个小于左边界的矩形 - 用单调栈for ( …

大小字符判断

//函数int my_isalpha(char c)的功能是返回字符种类 //大写字母返回1&#xff0c;小写字母返回-1.其它字符返回0 //void a 调用my_isalpha()&#xff0c;返回大写&#xff0c;输出*&#xff1b;返回小写&#xff0c;输出#&#xff1b;其它&#xff0c;输出&#xff1f; #inclu…

回归自然:拥抱生态农业

在这个喧嚣的时代&#xff0c;我们渴望回归大自然的怀抱&#xff0c;享受那份纯净与安宁。广西生态农业&#xff0c;正是我们追寻自然、健康生活的理想选择。它摒弃了传统农业的弊端&#xff0c;采用环保、可持续的种植方式&#xff0c;为我们带来了绿色、无污染的农产品。生态…

关于python中屏蔽输出

python中屏蔽输出包含屏蔽标准输出&#xff08;比如打印出来的内容&#xff09;、屏蔽标准错误&#xff08;错误信息&#xff09;还有屏蔽logging信息等。 屏蔽标准输出 import contextlib import oswith open(os.devnull, "w") as devnull:with contextlib.redire…

内网渗透测试笔记

内网渗透流程&#xff1a;打通->拿权限->留后门->放后台->攻击其他人 msf小知识: setg->设置全局变量; 监听模块(必须掌握):exploit/multi/handler; 为什么很多时候优选选择meterpreter的载荷?因为这个是msf的集成工具,使用更快捷,方法和工具更多;例 如:ru…