目录
思考
进入到主题之前,我们先来思考这样几个问题:
代码是什么样的?
计算机这门学科是什么样的?
计算机科学需要什么?1.代码应该是简洁和美丽的
2.计算机科学是一门艺术科学!
3.需要我们发挥想象力和创造力去写代码,而代码如人生-发现生活中的美,映射到代码上
4.代码是给别人看的:写代码可读性第一,资源排第二
5.为未来复用扩充维护写代码,依据七大原则(其中开闭最重要!)
发挥你的想象力到我们工厂模式里:
我们知道在工厂方法中,每次增加一个工厂,需要新写一个工厂和一个实现类,在需要另一种产品时,需要修改客户端,可是我懒啊,工厂、实现类、客户端我都不想再写。思考一下:我们开发人员能够通过代码编写实现功能,那机器能不能帮我做这件事?答案是肯定的!
需求:让计算机帮我们实现自动化的添加工厂、实现类、客户端
第三页比较第一页
巨大进步:
代码命名规范;
使用4个if变为了使用Switch,不用做三次无用功。
增加了判断了除数不为0的逻辑
捕捉了异常信息;
第六页比较第三页
需求:在web端实现了一款计算器,想要实现手机端计算器。
实现:前后端分离,后端可以复用,写无数个前端
打包构建时,可以分开构建,不用在每次构建全部-节约资源cpu内存时间
便于维护,改动时只改动后端或前端
第九页比较第六页:
需求:有一个新的运算,不想修改代码。
实现:将运算类的业务抽象,封装。新添加的运算类继承父类,多态
更加可扩展:有新需求,直接添加类,不用修改代码
在执行时,只用执行某一算法,不用编译其他算法
简单工厂
优点:
和不使用工厂相比实现了封装和部分解耦
不用关注实现的过程,创建对象和使用对象进行了分离,对象创建由工厂类负责(巨大进步)
缺点:
违背开闭原则:想要修改需求,需要修改工厂类
扩展性差:我想增加一个计算方法:开方,除了新增一个开方类,还需要修改工厂类方法
代码实现:
运算类
public class Operation { private double NumberA=0; private double NumberB=0; public double GetResult(){ double result=0; return result; } public double getNumberA() { return NumberA; } public void setNumberA(double numberA) { NumberA = numberA; } public double getNumberB() { return NumberB; } public void setNumberB(double numberB) { NumberB = numberB; } } public class OperationAdd extends Operation { @Override public double GetResult(){ double result=0; result =getNumberA()+getNumberB(); return result; } }
工厂类:
public class OperationFactory { public static Operation createOperate(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 OperationDiv(); break; } return oper; } }
工厂方法
优点:
具体创建对象由工厂子类实现,增加新实现类不用修改代码,符合开闭原则;
结构清晰简单:职责明确
缺点:
每次增加一个工厂,需要新写一个工厂和一个实现类
在需要另一种产品时,需要修改客户端
增加了系统资源的使用(创建新类)
巨大进步:
符合开闭原则:解决了简单工厂 较简单工厂相比扩展性高:工厂实现类越来越多,如果都在一个工厂方法里,方法臃肿。使用工厂方法模式增加工厂利于维护和扩展。
适用场景:
创建对象的逻辑较复杂;经常需要添加新类;
代码实现
public interface IFactory { Operation CreateOperation(); }
public class Operation { private double numberA=0; private double numberB=0; public double GetResult() throws Exception { double result=0; return result; } }
public class OperationAdd extends Operation{ public double GetResult(){ double result=0; result=getNumberA()+getNumberB(); return result; } }
public class AddFactory implements IFactory { @Override public Operation CreateOperation() { return new OperationAdd(); } }
提问:
大话上的简单工厂,工厂方法,抽象工厂为什么叫工厂?
工厂方法存在什么问题?
抽象工厂对比工厂方法有什么优点?。。。
要经常提出问题,无限思维进行发散。
发挥想象力+创造力
需求:让我们先来想一下,我们写完代码后,机器怎么帮我们实现代码的?
分析思考:我们写了一个.java文件,首先要经过javac编译成.class文件,再将.class文件由jvm类加载器进行加载到内存中。
实现思路
1、首先我们需要提供一个模板,计算机才可以根据模板去动态的创建类
2、生成运算类、工厂以及Client之后,需要调用对应的运算方法进行运算,需要进行动态编译,然后利用反射执行。
3、如果我们想在程序运行中,添加类并且想要其执行运行,该如何做?首先是需要将新加的类被知道,暂时有两种方式:动态注册或扫描。之后利用编译工具进行编译,最后反射执行。
小试牛刀一:实现扫描
思路:
用到的方法:编译,扫包,反射
1.读取我们写好的模板(客户端和工厂类),获取到.java文件对应的模板内容;
2.扫描算法类包,获取所有的算法类的,并获取到各类名;
3.替换模板中的占位符;
4.通过I/O输入输出流,创建新的.java文件,即算法工厂类和算法客户端类
代码
文件结构:
通过资源进行下载:
https://download.csdn.net/download/aqiuisme/87614180
小试牛刀二:实现注册
思路
用到的方法:热加载,编译,反射
1.用户在前端输入想要创造运算类的类名和运算符号去触发
2.读取运算类模板,然后将模板中的占位符替换为用户输入的
3.生成类文件
4.使用Java中的Compiler,将生成的三个类进行动态编译为.class文件
5.通过反射执行客户端中的运算方法
代码
文件结构:
通过资源进行下载:
https://download.csdn.net/download/aqiuisme/87614192
总结
我们将重复性的工作交给计算机去完成。这样不仅降低开发和维护的成本还减少了人为操作出错的几率!有没有眼前一亮的感觉?
但其实还是有缺点:比如扫描:一直扫描会占用资源
思考一下如何自动化并且资源不会一直被占用呢?
更新中…敬请期待