个人风格系列笔记,不会太详细,不喜勿喷,适用于复习设计模式而做。
实现一个简单计算器代码(加减乘除)
/** * 运算类 * created by callmedevil on 2019/5/26. */ public class operation { /** * 获取运算结果 * @param numa 数值a * @param numb 数值b * @param operate 运算符 * @return */ public static double getresult(double numa, double numb, string operate) { double result = 0l; switch (operate) { case "+": result = numa + numb; break; case "-": result = numa - numb; break; case "*": result = numa * numb; break; case "/": result = numa / numb; break; default: break; } return result; } }
/** * 测试类 * created by callmedevil on 2019/5/26. */ public class test { public static void main(string[] args) { operation operation = new operation(); double numa = 10; double numb = 2; system.out.println("加法:" + operation.getresult(numa, numb, "+")); system.out.println("减法:" + operation.getresult(numa, numb, "-")); system.out.println("乘法:" + operation.getresult(numa, numb, "*")); system.out.println("除法:" + operation.getresult(numa, numb, "/")); } }
但是这样就有个问题,如果这个计算器还需要实现开根号运算呢?难道就直接在operation类添加一个switch分支就行了吗?不是的,这样会让原来良好运行的代码产生变化,风险太大,因此需要将各种运算的逻辑分离开来,此处引入简单工厂模式。
又称为静态工厂模式,根据工厂类传入的参数动态决定创建某种类(这些类都继承自同一父类或实现同一接口)的实例。
/** * 运算基础类 * created by callmedevil on 2019/5/26. */ public class baseoperation { private double numa; private double numb; // 此处省略get、set方法 /** * 获取结果 * @return */ public double getresult() { double result = 0l; return result; } }
/** * 加法运算 * created by callmedevil on 2019/5/26. */ public class operationadd extends baseoperation { @override public double getresult() { return getnuma() + getnumb(); } }
/** * 减法运算 * created by callmedevil on 2019/5/26. */ public class operationsub extends baseoperation { @override public double getresult() { return getnuma() - getnumb(); } }
/** * 乘法运算 * created by callmedevil on 2019/5/26. */ public class operationmul extends baseoperation { @override public double getresult() { return getnuma() * getnumb(); } }
/** * 除法运算 * created by callmedevil on 2019/5/26. */ public class operationdiv extends baseoperation { @override public double getresult() { if (getnumb() == 0){ throw new runtimeexception("除数不能为0!"); } return getnuma() / getnumb(); } }
/** * 测试类 * created by callmedevil on 2019/5/26. */ public class test { public static void main(string[] args) { // 实现其他运算只需要更改输入的运算符即可 baseoperation operation = operationfactory.createoperation("+"); operation.setnuma(10); operation.setnumb(2); system.out.println("加法:" + operation.getresult()); } }
将每种运算的具体实现分离在不同的类中,工厂类只需要负责根据输入的运算符来创建对应的运算类实例即可。比如要一个开方运算是吧,那么需要创建一个开方运算类,同样继承baseoperation,接着在工厂类中switch中添加一个case分支,然后客户端便能够跟其他运算一样调用。
可能有人会问,这里不也同样是修改了switch分支条件吗?有什么区别?问得好,说明有思考过,但是原因也很明显,要仔细想想。把四种基础运算具体实现分离出去,工厂类中就包含了四行创建实例的代码,这时修改了switch分支的风险,和普通实现方式的风险相比,哪个大已经不用细说了吧。
这里案例代码比较简单,所以看起来会非常明朗,想必不必多说读者应该也能稍有体会。假如每个类型的运算非常复杂,甚至与其他模块关联,那使用设计模式的好处就体现出来了,比起全部代码堆在一个switch case上,在单独的一个类里面会更好维护和扩展吧?想做到完全不修改switch的代码是不可能,最重要的是我们达到了松耦合、可复用、可扩展目的,同时还降低了风险,有何不可。
如对本文有疑问, 点击进行留言回复!!
【面试题】研究过tomcat的NioEndpoint源码吗?请阐述下Reactor多线程模型在tomcat中的实现。
荐 厉害了!阿里P8架构师用4大技术文档带你深入解读爆火的中台战略
网友评论