设计模式-工厂方法模式

news2025/1/20 1:51:06

大话设计模式这本书反反复复学过好多遍了,每一次学都会有不同的认识,接下来谈谈我最近学习工厂的一次感受;

发展:

一个计算器的例子从不使用工厂到分离出前端、后端,到使用简单工厂再到使用工厂方法,每一步的变化都是巨大的;

简单实现:

简单实现的版本中存在着大量的问题,命名不规范啊,除数不能为0,前后端没有进行分离导致无法复用后端;违反开闭原则,新增运算的业务需要修改代码才可以;

首先命名不规范,我们写代码是为了给别人看的,不是能运行就可以,一个好的程序员写出来的代码要能让被人看一眼就能知道你这里写的是什么,如果我们随便对变量进行命名,任谁来也不能马上知道你写的是什么意思,所以命名不规范就导致了你写的这段程序一个人开发的,维护的时候,需要一百个人来维护,浪费人力、物力、财力,千万不要小看命名的问题;

再到除数不能为0的问题,这里问题就更严重了,只有没有把用户当猪的开发者才能写出这种代码,没有把用户当猪,总想着用户能知道除法运算中除数不能为0,把这种生死权交在了用户的手中,只有用户在使用软件的过程中按照正确的方式输入才可以使用,但是如果用户没有按照正确的方式输入的,那你的系统岂不是直接挂了,在用户看来就是这什么软件啊,我输入个0都不行,导致用户骂你,骂你的软件,用户是你最大的收益,用户不用了,你也就失业了。

开闭原则问题:我们说写代码不按照6大设计原则写的写出来的代码都是垃圾,我们写代码是为了让别人复用的;写了一段程序,别人想用的话你这还得改来改去,想想,这样别人会用吗?

想象力创造力:

创造力是基于想象力的,没有想象力,创造力根本无法实施,航天工程固然伟大,相比来说嫦娥奔月这个想法更加伟大,没有嫦娥奔月的想象力是不可能造出航天飞行器的;

这是一个工厂方法模式的类图, 接下来代码实现:

public abstract class Operation {
    private double numberA = 0;
    private double numberB = 0;

    public abstract double GetResult() throws Exception;

    public double getNumberA() {
        return numberA;
    }

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

    public double getNumberB() {
        return numberB;
    }

    public void setNumberB(double numberB) {
        this.numberB = numberB;
    }
}
public interface OperationFactory {
    Operation createOperate();
}
public class OperationAdd extends Operation {
    @Override
    public double GetResult() {
        return getNumberA()+getNumberB();
    }
}
public class OperationFactoryAdd implements OperationFactory {
    @Override
    public Operation createOperate() {
        return new OperationAdd();
    }
}
public static void main(String[] args) throws Exception {
        OperationFactory operationFactory = new OperationFactoryAdd();
        Operation operate = operationFactory.createOperate();
        operate.setNumberA(11);
        operate.setNumberB(22);
        double result = operate.GetResult();
        System.out.println(result);
    }

首先是发现力:

以此我们发现运算类工厂中的代码基本都是一致的,只有涉及到创建出不用运算类对象的名字部分是不一样的;

接下来是想象力:

我们就想,既然代码基本都是一致的,我可不可以写一个模板,让程序来帮我写工厂的这段代码,这样每当我有一个写的运算类添加的时候,这样重复性的东西就不用手写了呀;

有了这样的想象力之后是创造力:

工厂模板,用于让程序帮我们实现自动写代码

public class FactoryTemplate {
    public String createFactory(String operationName) throws Exception{
        String srcFactoryCode = "package com.mengjie.saomiao.operationFactory;\n" +
                "import com.mengjie.saomiao.Operation;\n" +
                "import com.mengjie.saomiao.OperationFactory;\n" +
                "import com.mengjie.saomiao.operation."+operationName+";\n" +

                "public class" + " " + operationName+"Factory" + " " + "implements OperationFactory {\n" +
                "    @Override\n" +
                "    public Operation createOperate() {\n" +
                "        return new" + " " + operationName + "();\n" +
                "    }\n" +
                "}";
        String srcFilePath = "E:\\study\\Practice\\auto\\src\\main\\java\\com\\mengjie\\saomiao\\operationFactory\\" + operationName+"Factory" + ".java";
        FileWriter fileWriter = null;
        File file = new File(srcFilePath);
        if (!file.exists()) {
            file.createNewFile();
        }
        fileWriter = new FileWriter(srcFilePath);
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        bufferedWriter.write(srcFactoryCode);
        bufferedWriter.close();
        return srcFilePath;

    }
}

编译工具类,用于我们让程序帮我们写出来代码时候,新增的工厂类没有编译成字节码文件的话我们的程序是没有办法帮我们执行的;

public class Compiler {
    private String classPath;

    private String filePath;

    public Compiler(String classPath, String filePath) {
        this.classPath = classPath;
        this.filePath = filePath;
    }

    public void compiler() {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        int status = compiler.run(null, null, null, "-d",classPath,filePath);
        if(status!=0){
            System.out.println("没有编译成功!");
        }
    }
}

自动扫描,每次都获取一个文件夹中的所有的运算类,将类名最终截取出来,传入创建工程类的模板中让程序来帮我们写代码;

public class Scan {
    public void scan() throws Exception {
        String packagePath = "E:\\study\\Practice\\auto\\src\\main\\java\\com\\mengjie\\saomiao\\operation";

        File file = new File(packagePath);
        if (file.isDirectory()){
            File[] files = file.listFiles();
            Map<Object, Method> map = new HashMap<>();
            for (File f : files){
                String fileName = f.getAbsolutePath();
                if (fileName.endsWith(".java")){
                    String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".java"));
                    String replacedName = className.replace("com\\mengjie\\saomiao\\operation\\", "");
                    FactoryTemplate factoryTemplate = new FactoryTemplate();
                    String factoryClassPath = factoryTemplate.createFactory(replacedName);

                    //调用一个编译源码的方法,将创建出的.java文件编译成.class文件
                    Compiler compilerOperation = new Compiler(System.getProperty("user.dir")+"\\auto\\target\\classes",fileName);
                    compilerOperation.compiler();

                    //调用一个编译源码的方法,将创建出的.java文件编译成.class文件
                    Compiler compilerFactory = new Compiler(System.getProperty("user.dir")+"\\auto\\target\\classes",factoryClassPath);
                    compilerFactory.compiler();

                    ClientTemplate clientTemplate = new ClientTemplate();
                    String clientClassPath = clientTemplate.createClient(replacedName);
                    //调用一个编译源码的方法,将创建出的.java文件编译成.class文件
                    Compiler compilerClient = new Compiler(System.getProperty("user.dir")+"\\auto\\target\\classes",clientClassPath);
                    compilerClient.compiler();

                    String compileClassName = "com.mengjie.saomiao.client."+replacedName+"Client";

                    Class<?> classLoaderClass = Class.forName(compileClassName);
                    Object instance = classLoaderClass.getConstructor().newInstance();
                    Method method = classLoaderClass.getMethod("main",String[].class);

                    map.put(instance,method);
                    method.invoke(null,  new String[]{""});
                }
            }
        }
    }
}

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

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

相关文章

第一性原理计算在材料分析中的应用及未来发展趋势

第一性原理计算是一种理论计算方法&#xff0c;能够基于量子力学原理对物质的性质进行高精度预测。它已经成为材料科学研究中不可或缺的工具&#xff0c;帮助我们了解材料的基本特性&#xff0c;优化材料的性能&#xff0c;并发现新的材料。 一、第一性原理计算的基本原理 第一…

zabbix故障排查

zabbix server服务问题可以查看server日志 tail -f /var/log/zabbix/zabbix_server.log 根据日志中的error报错提示分析原因 zabbix agent服务问题可以查看agent日志 tail -f /var/log/zabbix/zabbix_agentd.log 根据日志中的error报错提示分析原因 zabbix的nginx服务问题可…

Window下编译PJSIP,不编译Media模块

Windows系统下使用VS1027进行编译PJSIP。 下载地址 PJSIP的地址&#xff1a;https://github.com/pjsip/pjproject 在线clone太慢的话&#xff0c;可以直接在这里下载比clone会快很多&#xff1a; https://github.com/pjsip/pjproject/releases 安装OpenSSL 直接安装已经编译…

TitanIDE 新版本来袭,全新“效能看板”上线

TitanIDE产品团队于4月17日晚发布了TitanV2.6.3版本&#xff0c;作为一次重要的版本迭代&#xff0c;新版本主要增加/优化了以下重大功能&#xff1a; 全新效能看板上线&#xff0c;研发进度一目了然&#xff1b;新增代码拷贝、下载权限管理功能&#xff1b;项目启动提速&…

创客匠人视频号全域增长落地班成功举办

以专业赋能好老师&#xff0c;打造知识付费商业IP&#xff0c;借助视频号布局商业增长第二曲线。 4月15日-16日&#xff0c;泛知识场景数字化服务商创客匠人在厦门举办「视频号全域增长落地班」。 本次大会邀请到创客匠人CEO、中欧EMBA蒋洪波&#xff0c;福布斯环球联盟创新企业…

电脑开机进不了系统怎么办?电脑开机错误无法显示桌面解决方法

电脑开机进不了系统怎么办&#xff1f;很多用户都有遇到过电脑正常开机&#xff0c;但是无法进入到系统桌面的情况。其实遇到这个问题&#xff0c;大部分的原因都是因为系统出现了故障损坏&#xff0c;我们可以去通过U盘来重装系统的方法进行解决。一起来看看以下的具体操作方法…

jar包反编译工具(java-decompiler)

五种反编译工具 1.jd-gui 下载地址&#xff1a;http://java-decompiler.github.io/ 优点&#xff1a;反编译的源代码基本符合&#xff0c;没有乱七八糟新增的修饰符 缺点&#xff1a;反编译过程耗时较长&#xff08;50MB需要10分钟左右&#xff09; 无法还原内部类 可以查看对…

DDPG算法详解

DQN算法详解 一.概述 概括来说&#xff0c;RL要解决的问题是&#xff1a;让agent学习在一个环境中的如何行为动作(act)&#xff0c; 从而获得最大的奖励值总和(total reward)。 这个奖励值一般与agent定义的任务目标关联。 agent需要的主要学习内容&#xff1a;第一是行为策略…

leetcode刷题(5)

各位朋友们&#xff0c;大家好&#xff0c;今天是我leedcode刷题的第五篇&#xff0c;我们一起来看看吧。 文章目录 栈的压入&#xff0c;弹出序列题目要求用例输入提示做题思路代码实现C语言代码实现Java代码实现 最小栈题目要求用例输入提示做题思路代码实现Java代码实现 栈的…

QML自定义模块及qmldir的使用

前言 在开发QtQuick项目中&#xff0c;当项目文件很多的情况下&#xff0c;可能会分成多级文件夹来进行分类&#xff0c;还有一些通用类型文件&#xff0c;如公共组件&#xff0c;通用配置等等&#xff0c;需要在各个不同的文件中进行调用&#xff0c;这种情况下&#xff0c;一…

04、Cadence使用记录之器件连接的连线、网络、总线、差分(OrCAD Capture CIS)

04、Cadence使用记录之器件连接的连线、页内网络、总线、跨页网络、差分、电源&#xff08;OrCAD Capture CIS原理图&#xff09; 前置教程&#xff1a; 01、Cadence使用记录之新建工程与基础操作&#xff08;原理图绘制&#xff1a;OrCAD Capture CIS&#xff09; 02、Cadenc…

操作系统原理 —— 操作系统的四个特征:并发、共享、虚拟、异步 (二)

本章我们来聊一下操作系统的四个特征 在我们的操作系统中有四个特征&#xff1a;并发、共享、虚拟、异步&#xff0c;我们结合每一个特征来进行讲解&#xff0c;我们先来看并发。 并发 这里所说的并发&#xff0c;最好不联想到并发编程。咱们就简简单单理解一下&#xff0c;…

浙工商机器学习课程论文+代码分享(含数据集)

文章目录 一、论文总览二、摘要 & 目录三、数据集的展示四、部分代码4.1 降低内存4.2 部分特征生成4.3 热力图分析4.4 变量分布图4.5 聚类算法4.6 聚类结果的展示&#xff08;部分&#xff09;4.7 聚类后的特征图 完整版的论文代码数据集地址&#xff1a; https://mbd.pub…

leetcode刷题(7)二叉树(1)

哈喽大家好&#xff0c;这是我leetcode刷题的第七篇&#xff0c;这两天我将更新leetcode上关于二叉树方面的题目&#xff0c;如果大家对这方面感兴趣的话&#xff0c;欢迎大家持续关注&#xff0c;谢谢大家。 那么我们就进入今天的主题。 文章目录 1.二叉树的前序遍历题目要求示…

优先级队列

目录 前言&#xff1a; 1、PriorityQueue的特性 .2 PriorityQueue常用接口介绍 Ⅰ、PriorityQueue常见的构造方法 Ⅱ、常用的方法 Ⅲ、PriorityQueue的扩容方式&#xff1a; 3、应用 前言&#xff1a; 普通的队列是一种 先进先出的数据结构&#xff0c;元素在队列尾追加&am…

RC专题:无源滤波电路和有源滤波电路

什么是无源滤波电路和有源滤波电路 仅由无源器件&#xff08;电阻、电容、电感&#xff09;构成的滤波电路 称为无源滤波电路。如下图所示。 由无源器件和有源器件&#xff08;双极型管&#xff0c;单极型管&#xff0c;集成运放&#xff09;构成的滤波电路 称为有源滤波电路。…

什么是爬虫?

网络爬虫&#xff08;又被称为网页蜘蛛&#xff0c;网络机器人&#xff0c;在FOAF社区中间&#xff0c;更经常的称为网页追逐者&#xff09;&#xff0c;是一种按照一定的规则&#xff0c;自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟…

2023第十三届MathorCup高校数学建模挑战赛C题解析

2023第十三届MathorCup高校数学建模挑战赛C题解析 题目解析前言题目一题目二题目三题目四 题目 C 题 电商物流网络包裹应急调运与结构优化问题 电商物流网络由物流场地&#xff08;接货仓、分拣中心、营业部等&#xff09;和物流场地之间的运输线路组成&#xff0c;如图 1 所示…

LeetCode:1. 两数之和——哈希表~

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340; 算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 一、&#x1f331;1. 两数之和 题目描述&#xff1a;给定一个整数数组nums 和一个整数目…

QT 插件通信接口调用 CTK开发(四)

CTK 为支持生物医学图像计算的公共开发包,其全称为 Common Toolkit。为医学成像提供一组统一的基本功能;促进代码和数据的交互及结合;避免重复开发;在工具包(医学成像)范围内不断扩展到新任务,而不会增加现有任务的负担;整合并适应成功的解决方案。 本专栏文章较为全面…