• 设计模式 简单工厂模式的进化过程


    先看一个小故事:
    你是一个工匠,得到一个紧急的任务,要求刻版印刷 “喝酒唱歌 人生真爽” ,由于任务紧急,你不得不通宵,终于刻好了。

    第二天,客户突然觉得 “喝酒唱歌” 这几个字有点俗,觉得改成 “对酒当歌 人生真爽” 比较好,你又熬夜刻制好了。

    第三天,客户想了想,觉得 “人生真爽” ,太过直接,要求改成 “对酒当歌 人生几何” ,虽然你很生气,但是你只能忍着,你又熬夜重新刻制好。

    任务完事了,你就想,如果再遇到了改来改去的客户,有什么好办法能减少你的工作量呢?

    没错,你可以把几个字分开刻,不要把所有字都刻在一起,而是刻八个板,每个板刻一个字,如果有变动,不用所有的工作都重头做,只需要修改变动的部分就可以。工作量一下减少了一半。

    这就是中国古代的活字印刷啊。

    通过这样的方法,可以做到 可维护(只需要修改有变动的字)、可复用(两次需求重复的字不用再刻制一遍)、可扩展(若要加字,只需要另外刻字加入即可)、灵活性好(字的排列方式横竖可以随意改)

    看完这个小故事,下面思考一个题目:

    使用面向对象的语言,要求输入两个数和运算符号,得到结果。

    1

    最简单的做法,我们可以获取用户输入的两个数字和运算符号,判断运算符号直接进行运算就可以得到结果;

    (此处为了偷懒,我只写了加法和乘法两种运算)

    1. //此处我只写了加法和乘法两种运算
    2. public static void main(String[] args) {
    3. Scanner input=new Scanner(System.in);
    4. System.out.println("请输入第一个数字:");
    5. int num1=input.nextInt();
    6. System.out.println("请输入运算符:");
    7. String yunsuanfu=input.next();
    8. System.out.println("请输入第二个数字:");
    9. int num2=input.nextInt();
    10. switch(yunsuanfu){
    11. case "+":
    12. System.out.println(num1+yunsuanfu+num2+"="+(num1+num2));
    13. break;
    14. case "*":
    15. System.out.println(num1+yunsuanfu+num2+"="+(num1*num2));
    16. break;
    17. }
    18. }

    但这显然有问题,根本没有使用到面向对象的思想。假如把需求修改成写一个计算器,现在的代码能不能复用呢?

    2

    下面我们尝试修改,先让业务逻辑和界面逻辑分开

    业务逻辑代码:

    1. public class Yunsuan1 {
    2. public static int getResult(int num1, int num2, String yunsuanfu) {
    3. int result = 0;
    4. switch (yunsuanfu) {
    5. case "+":
    6. result = num1 + num2;
    7. break;
    8. case "*":
    9. result = num1 * num2;
    10. break;
    11. }
    12. return result;
    13. }
    14. }

    界面逻辑代码:

    1. import java.util.Scanner;
    2. public class Test1 {
    3. public static void main(String[] args) {
    4. Scanner input=new Scanner(System.in);
    5. System.out.println("请输入第一个数字:");
    6. int num1=input.nextInt();
    7. System.out.println("请输入运算符:");
    8. String yunsuanfu=input.next();
    9. System.out.println("请输入第二个数字:");
    10. int num2=input.nextInt();
    11. int result= Yunsuan1.getResult(num1,num2,yunsuanfu);
    12. System.out.println("结果是:"+result);
    13. }
    14. }

    如上的代码使用了面向对象的封装

    现在假如要写一个计算器的应用程序,就可以把业务逻辑的代码复用了。

    不单是web程序、手机等移动系统的软件也可以复用。

    3

    现在我们来思考,假如要添加一个指数运算,此时就要修改整个逻辑代码文件,有可能失误把已经写好的加法运算改错,又比如,公司新增了一个岗位,现在要求你为公司的薪资管理做维护,公司就必须把整个逻辑代码文件给你修改,你心中小算盘一打,“TMD,公司给我的工资这么低,这下有机会了。”

    比如switch是你自己的时候,你把你的工资加20%。本来是让你加一个功能,却使得原来良好的功能代码发生了变化,这风险太大了。

    那么我们应该做到 修改其中一种运算,不影响其他运算。我们来使用面向对象的继承和多态。

    从不同的运算抽象出Yunsuan父类

    1. package com.qing.jdgc;
    2. public abstract class Yunsuan {
    3. public abstract void getResult(int num1,int num2);
    4. }

    子类继承 Yunsuan父类,不同的运算(加法、乘法、指数运算)执行的运算操作是不一样的,重写计算的方法。

    1. package com.qing.jdgc;
    2. public class Jiafa extends Yunsuan{
    3. @Override
    4. public void getResult(int num1, int num2) {
    5. System.out.println(num1+"和"+num2+"执行加法运算后结果是:"+(num1+num2));
    6. }
    7. }
    1. package com.qing.jdgc;
    2. public class Chengfa extends Yunsuan {
    3. @Override
    4. public void getResult(int num1, int num2) {
    5. System.out.println(num1 + "和" + num2 + "执行乘法运算后结果是:" + (num1 * num2));
    6. }
    7. }
    1. package com.qing.jdgc;
    2. public class Zhishu extends Yunsuan{
    3. @Override
    4. public void getResult(int num1, int num2) {
    5. System.out.println(num1+"和"+num2+"执行指数运算后结果是:"+(Math.pow(num1,num2)));
    6. }
    7. }

     根据不同的运算符号实例化出不同的对象(多态),接下来执行不同的运算

    1. package com.qing.jdgc;
    2. public class Factory {
    3. public static Yunsuan createYunsuan(String yunsuanfu){
    4. Yunsuan yunsuan = null;
    5. switch(yunsuanfu){
    6. case "+":
    7. yunsuan=new Jiafa();
    8. break;
    9. case "*":
    10. yunsuan=new Chengfa();
    11. break;
    12. case "^":
    13. yunsuan=new Zhishu();
    14. break;
    15. }
    16. return yunsuan;
    17. }
    18. }

     界面逻辑

    1. package com.qing.jdgc;
    2. import java.util.Scanner;
    3. public class Test {
    4. public static void main(String[] args) {
    5. Scanner input=new Scanner(System.in);
    6. System.out.println("请输入第一个数字:");
    7. int num1=input.nextInt();
    8. System.out.println("请输入运算符:");
    9. String yunsuanfu=input.next();
    10. System.out.println("请输入第二个数字:");
    11. int num2=input.nextInt();
    12. Factory.createYunsuan(yunsuanfu).getResult(num1,num2);
    13. }
    14. }

    结果

     

     

    接下来,回到正题,简单工厂模式

    简单工厂模式又叫静态工厂方法,属于类创建型模式。

    特点如下

    可以根据参数的不同,返回不同的实例。


    简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

    如上的最后一次的代码就使用了简单工厂模式,Factory类就可以根据不同的运算符返回不同的实例。

  • 相关阅读:
    NVMe开发——PCIe复位
    创新案例分享 | 运维完善税务局信息管理系统,保障系统稳定高效运行
    顺序编码器--OrdinalEncoder类
    【UCIe】UCIe 支持的协议及操作模式
    适配器模式:如何让不兼容的接口变得兼容
    记一次gitlab平台任意用户注册引发的源代码泄漏
    win10系统单独编译和使用WebRTC的回声消除(AEC)、音频增益(AGC)、去噪(NS)模块
    【全开源】Java共享茶室棋牌室无人系统支持微信小程序+微信公众号
    解析G代码【C#】
    推荐系统方法梳理
  • 原文地址:https://blog.csdn.net/m0_45877477/article/details/126574127