一个计算器的例子从不使用工厂到分离出前端、后端,到使用简单工厂再到使用工厂方法,每一步的变化都是巨大的;
简单实现的版本中存在着大量的问题,命名不规范啊,除数不能为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[]{""});
}
}
}
}
}
工厂方法模式提供了一种将对象的创建与使用分离的方式,通过定义一个创建对象的工厂接口,让子类决定实例化哪个具体类。工厂方法模式可以在不知道具体对象类型的情况下创建对象,使代码更加灵活和可扩展。