1. 业务场景讲解设计模式(简单工厂模式)

news2024/11/23 8:37:18

现阶段我之所以再次学习设计模式,是因为感受到企业项目的多层封装与调用的复杂性,既然这样那肯定是有自己的设计道理的,能让系统更具有拓展性,安全性,易维护性。所以,我希望这次站在领导设计者的角度去实现功能,而不是简单的增删改查。

目录

  • 1 实现一个计算器
  • 2 初步解耦代码
  • 3 深度解耦代码
  • 4 总结很重要

1 实现一个计算器

现在我们什么都不考虑,仅仅使用Java实现一个计算器

/**
 * 简单实现计算器
 * 设计:依次输入数字A,运算符号,数字B
 */
public class calculator {
    public static void main(String[] args) {

        System.out.println("请输入数字A:");
        Scanner strNumberA = new Scanner(System.in);
        Double numberA = strNumberA.nextDouble();

        System.out.println("请选择运算符:+ - * /");
        Scanner strOperate = new Scanner(System.in);
        String operate = strOperate.next();

        System.out.println("请输入数字B:");
        Scanner strNumberB = new Scanner(System.in);
        double numberB = strNumberA.nextDouble();

        //计算
        switch(operate){
            case "+":
                System.out.println(numberA + numberB);
                break;
            case "-":
                System.out.println(numberA - numberB);
                break;
            case "*":
                System.out.println(numberA * numberB);
                break;
            case "/":
                System.out.println(numberA / numberB);
                break;

        }

    }
}

简单测试一下
在这里插入图片描述

2 初步解耦代码

现在我的需求变了,我觉得这个代码中算法和页面混在一起很臃肿。若我需要调整数据展示的样式,就会被看到全部的代码,也不安全。因此我本能的希望可以将这两部分隔开。
那现在就成了这样,一部分负责算法,一部分负责展示。


/**
 * 计算部分
 */

public class calculator01 {
    public void getOpertion(double numberA,double numberB,String operate){
        //计算
        switch(operate){
            case "+":
                System.out.println(numberA + numberB);
                break;
            case "-":
                System.out.println(numberA - numberB);
                break;
            case "*":
                System.out.println(numberA * numberB);
                break;
            case "/":
                System.out.println(numberA / numberB);
                break;

        }
    }


}


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

        System.out.println("请输入数字A:");
        Scanner strNumberA = new Scanner(System.in);
        Double numberA = strNumberA.nextDouble();

        System.out.println("请选择运算符:+ - * /");
        Scanner strOperate = new Scanner(System.in);
        String operate = strOperate.next();

        System.out.println("请输入数字B:");
        Scanner strNumberB = new Scanner(System.in);
        double numberB = strNumberB.nextDouble();

        calculator01 calculator01 = new calculator01();
        calculator01.getOpertion(numberA, numberB, operate);
    }
}

3 深度解耦代码

我现在又又有需求了,我希望增加一个开根运算,你会怎么做呢?
是不是在算法类中,switch添加一个开根运算。
不错,但是这样我觉得还是有问题,就是我只让你增加一个开根运算,你就看到了我的其他算法实现(加减乘除),如果你将我的加法修改为减法,这对我也就太不安全了。所以我希望可以将每个算法都隔离开。

那怎么隔离呢?
先观察这些算法的实现,发现有共同点,就是都会传入两个参数。根据面向对象习惯,我打算提取出公共属性。例如,需要加法,我就创建一个名为加法的子类,继承运算类。
在这里插入图片描述

/**
 * 计算器的公共类:定义参数A,B,和运算结果
 */
public abstract class Operation {
    private double numberA = 0;
    private double numberB = 0;

    public double getNumberA() {
        return numberA;
    }

    public void setNumberA(double numberA) {
        this.numberA = numberA;
    }

    public double get_NumberB() {
        return numberB;
    }

    public void setNumberB(double numberB) {
        this.numberB = numberB;
    }

    abstract double getResult();

}

/**
 * 加法类
 */
public class operationAdd extends Operation{
    @Override
    double getResult() {
        double result = 0;
        result = getNumberA() + get_NumberB();
        return result;
    }
}

/**
 * 减法类
 */
public class operationSub extends Operation{
    @Override
    double getResult() {
        double result = 0;
        result = getNumberA() - get_NumberB();
        return result;
    }
}

/**
 * 乘法类
 */
public class operationMul extends Operation{
    @Override
    double getResult() {
        double result = 0;
        result = getNumberA() * get_NumberB();
        return result;
    }
}
/**
 * 除法类
 */
public class operationDev extends Operation{
    @Override
    double getResult() {
        double result = 0;
        //除数不等于0
        if(get_NumberB()!= 0){
            result = getNumberA() / get_NumberB();
        }
        return result;
    }
}

不错,现在每种算法算法之间都做到了相互隔离,如果我们需要添加一个开根运算,只需要再添加一个类就可以了,这样系统的拓展性就很好。

此刻有一个新的问题,就是我如何调用呢,我如何让计算器知道我使用了哪种算法。
最简单粗暴的方式就是在客户端代码中,写一个switch判断传入的运算符号,创建对应的算法类对象。
可是这样一来,算法类不就又和界面展示混合了,干了半天白费功夫。所以我们希望将创建对应算法类对象的代码单独分离出去。
例如我们希望做减法,那么就传入这个类内部就会调用创建减法类的对象。
这种专门负责创建实例对象的家伙,就跟加工厂一样,因此就提出了简单工厂设计模式的概念。
在这里插入图片描述
下面看看代码感受一下吧

public class OperationFactory {
    public static Operation creatOperate(String operate){
        Operation oper = null;
        switch(operate){
            case "+":
                oper = new operationAdd();
                break;
            case "-":
                oper = new operationSub();
                 break;
            case "*":
                oper = new operationMul();
                break;
            case "/":
                oper = new operationDev();
                break;
            }
        return oper;
    }
}

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

        System.out.println("请输入数字A:");
        Scanner strNumberA = new Scanner(System.in);
        Double numberA = strNumberA.nextDouble();

        System.out.println("请输入数字B:");
        Scanner strNumberB = new Scanner(System.in);
        double numberB = strNumberB.nextDouble();


        System.out.println("请选择运算符:+ - * /");
        Scanner strOperate = new Scanner(System.in);
        String operate = strOperate.next();

        Operation operation = OperationFactory.creatOperate(operate);
        operation.setNumberA(numberA);
        operation.setNumberB(numberB);

        double result = operation.getResult();
        System.out.println(result);


    }
}

4 总结很重要

在上述案例中,我们将最开始的一坨代码按照需求,一步步优化解耦(专业名词叫:重构代码),最终分成了多个类。可以发现,最终的代码具有了很好的拓展性和可维护性。在案例中,我们是什么使用了工厂模式呢?是我们依据需求,将算法拆分到最后才考虑到的,并不是生硬的告诉大家直接使用工厂模式。希望大家可以真切的感受到设计模式的魅力。
这只是最初级的一个案例,下一章我们将介绍一个更有特色的案例,更贴近生活。

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

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

相关文章

如何为IP申请一个SSL证书?

打开www.zerossl.com官网,然后我们直接输入服务器的IP地址,然后直接点击Next Step。 接下来,我们输入自己的邮箱账号,直接注册。(如果点击后没有反应,请挂代理访问。) 然后我们到了下一页直接点…

mmcv与cuda,pytorch版本匹配要求

mmcv与cuda、pytorch版本兼容要求,见mmcv官方文档:https://mmcv.readthedocs.io/zh_CN/latest/get_started/installation.html#pip 安装部分。 目前网页上默认最新版2.x版本,若要切换旧版,点击页面左下角切换即可。 查看自己的cud…

面向对象设计原则和GOF23种设计模式

写在前面 本文一起看下面向对象的设计原则和GOF 23 种常用的设计模式。 1:面向对象设计原则 面向对象设计原则可以简单的总结为SOLID,分别看下。 1.1:S single responsibility principle,单一职责原则,即一个类只…

百叶隔断为空间添加时尚元素

百叶隔断作为一种常见的空间分隔方式,早已成为了许多家庭、工作场所不可缺少的装修元素之一。而在装修中,如何利用百叶隔断为间添加时尚元素呢? 1. 选择合适的材质 百叶隔断的材质种类繁多,包括木质、金属、PVC等等。在选择时&…

SIT1021,可替代TJA1021一款本地互联网络(LIN)物理层收发器

SIT1021 是一款本地互联网络(LIN)物理层收发器,符合 LIN 2.0、LIN 2.1、LIN 2.2、LIN 2.2A、 ISO 17987-4:2016 (12V) 和 SAE J2602 标准。主要适用于使用 1kbps 至 20kbps 传输速率的车载网 络。SIT1021 通过 TXD 引脚控制 LIN 总线的状态&a…

MPLS多协议标签交换

最初MPLS多协议标签交换和包交换是竞争关系 随着包交换的快速发展为特快包交换 MPLS最终落败但开展其它业务并且还使用了特快包交换中的FIB表 开展业务为: 解决BGP路由黑洞的最佳方案MPLS VPN MPLS TE 流量工程 MPLS多协议标签交换 工作过程 控制层面&#x…

【Apollo星火计划】—— Cyber基础概念|通信机制

文章目录 前言基本概念1Cyber简介通信构成Bazel简介 TEST1. 构建单包工程TEST2. 构建多包工程基本概念2话题通信服务通信参数通信数据通信基础ProtobufProtobuf简介Protobuf 文件编写Protobuf编译 TEST3. protobuf实验TEST4.C话题通信实践案例TEST5.C服务通信实践案例TEST6.C参…

electron dialog.showMessageBox使用案例

electron 版本&#xff1a;25.3.1 index.html <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>Hello World!</title><meta http-equiv"Content-Security-Policy" content"script-src self unsa…

在linux中进行arm交叉编译体验tiny6410裸机程序开发流程

在某鱼上找了一个友善之臂的Tiny6410开发板用来体验一下嵌入式开发。这次先体验一下裸机程序的开发流程&#xff0c;由于这个开发板比较老旧了&#xff0c;官方文档有很多过期的内容&#xff0c;所以记录一下整个过程。 1. 交叉编译器安装 按照光盘A中的文档《04- Tiny6410 L…

C语言非常道 c0609.c 练习6.8

结构类型处理复杂的数据 结构声明位于源文件的开头&#xff0c;相当于结构类型的全局声明 注意&#xff1a;读取或者写入某个文件&#xff0c;都要先打开文件 写入读出函数的参数类型&#xff0c;实参和形参的类型要对应&#xff1b; 上述&#xff1a; & emp 得到一个指向…

Appium+python自动化(二十一)- 让猴子按你指令大闹手机,让我们都成为耍猴高手(超详解)

耍猴第一式 - 隐藏命令 monkey隐藏的两个命令&#xff1a; 1 –pck-blacklist-file<黑名单文件><br><br>–pck-whitelist-file<白名单文件> monkey还有一个隐藏的命令那就是&#xff1a; 1 –f<脚本文件>:可以指定monkey的自定义脚本 一般…

批处理下载视频

一、安装annie Github 上 annie 下载神器的安装及使用教程: https://blog.csdn.net/qq_41780295/article/details/119795152 二、视频下载 安装了annie之后&#xff0c;我们就可以使用命令行下载视频文件了&#xff1b; 例如&#xff0c;打开B站&#xff0c;随便点开一个视频…

能耗监测管理系统

能耗监测管理系统是一种用于监测和管理能源消耗的软件系统&#xff0c;可以帮助企业、机构或个人实现对能源消耗的实时监控、分析和管理。随着能源问题的日益凸显&#xff0c;能耗监测管理系统的重要性也越来越受到人们的关注。本文将从以下几个方面介绍能耗监测管理系统。 一、…

springboot 项目启动不打印spring 启动日志

今天项目遇到一个很奇怪的问题&#xff0c;服务在启动时&#xff0c;不打印spring 的启动日志。经过排查发现是因为其他的依赖引入了 log4j 的依赖&#xff0c;因为我们的项目用的是logback&#xff0c;所以项目中没有log4j 的相关配置&#xff0c;所以干扰到了日志的打印 原因…

使用IntelliJ Idea开发Flink应用程序

使用IntelliJ Idea开发Flink应用程序 一、实验目的二、实验内容三、实验原理四、实验环境五、实验步骤5.1 启动IntelliJ Idea并创建flink项目5.2 编写flink代码5.2.1 准备工作5.2.2 批处理5.2.3 有界流处理5.2.4 无界流处理 ⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何…

剑指Offer第一章——整数

1. 整数 1.1 整数的基础知识 整数是一种基本的数据类型。编程语言可能会提供占据不同内存 空间的整数类型&#xff0c;每种类型能表示的整数的范围也不相同。例如&#xff0c;Java中有4种不同的整数类型&#xff0c;分别为8位的byte&#xff08;-&#xff5e;-1&#xff09;、…

Minecraft 1.20.x Forge模组开发 04.动画效果物品

我们本次实现一个具有动画效果的流星锤: 效果演示 效果演示 效果演示 首先,请确保你的开发包中引入了geckolib依赖,相关教程请参考:Minecraft 1.20.x Forge模组开发 03.动画生物实体 1.首先我们要使用geckolib制作一个物品和对应的动画: 在blockbench中新建一个

Android TelephonyManager双卡获取数据开启状态异常的可能原因

背景 应用内不指定subId获取数据状态可能会错误&#xff0c;因为可能拿到voice的能力&#xff0c;而非data。 代码逻辑 1、通过TelephonyManager的isDataEnabled()没有指定subId时&#xff0c;调用内部方法isDataEnabledForReason&#xff0c;传入getId()参数以指定subid&am…

设备监测诊断与维护:优化工业生产效率的关键措施

在现代工业生产中&#xff0c;设备的稳定运行对于保障生产效率至关重要。设备监测、诊断和维护作为关键措施&#xff0c;能够帮助企业及时发现设备问题、诊断故障原因&#xff0c;并采取有效维护措施&#xff0c;从而降低生产中断风险&#xff0c;提高生产效率。本文将深入探讨…

【二叉树】利用前序和中序遍历结果生成二叉树并输出其后序和层序遍历结果

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; ⭐️往期关于树的文章&#xff1a; 【哈夫曼树】基本概念、构建过程及C代码 【线索二叉树】C代码及线索化过程详解 欢迎阅读&#xff01; 实验内容 根据二叉树先序和中序遍历的结果,生成该二叉树。并…