> 文章列表 > 设计模式-工厂方法模式

设计模式-工厂方法模式

设计模式-工厂方法模式

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

发展:

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

简单实现:

简单实现的版本中存在着大量的问题,命名不规范啊,除数不能为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 {@Overridepublic double GetResult() {return getNumberA()+getNumberB();}
}
public class OperationFactoryAdd implements OperationFactory {@Overridepublic 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[]{""});}}}}
}