经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
大话设计模式笔记の 简单工厂模式
来源:cnblogs  作者:callmeDevil  时间:2019/5/27 8:52:21  对本文有异议

前言

个人风格系列笔记,不会太详细,不喜勿喷,适用于复习设计模式而做。

概要

  • 一个好的程序猿/媛敲出来的代码应该是可维护、可复用、可扩展的,也就是具有较好的灵活性。
  • 为了达到以上目的,在还没敲代码之前,需要事先考虑通过何种方式能够使自己的程序的耦合度降低,最基本的便是面向对象的封装、继承、多态
  • 但这往往是不够的,需要根据实际情况选择合适的设计模式使得程序变得更加灵活,容易修改,并且易于复用
  • 复用并不是复制的意思。在实际开发当中,有时候会遇到一些类似的功能,有一部分已经是在别的 Service 中实现了(整个方法的功能是不一样的),但可能出于项目赶进度的时候,也可能做这个功能的员工水平不足,于是乎直接将此处代码一顿操作 ctrl + C / V 一切搞定。但对日后维护的人来说是一场灾难,万一又是自己,日后少不了“早知如此,何必当初”的感叹了。养成好的编码习惯很重要。
  • 话说得好听谁都会,正是因为人都有成长的过程,所以对业务的理解转化为程序,以及编写代码的优美程度也是一步一个脚印走出来的。是否能够做到真正的松耦合,又或者“松”的过度导致程序过于臃肿,都跟个人的层次有关。付出不一定有收获,但不付出,肯定没有收获。

抛砖引玉

案例

实现一个简单计算器代码(加减乘除)

普通实现方式

  1. /**
  2. * 运算类
  3. * Created by callmeDevil on 2019/5/26.
  4. */
  5. public class Operation {
  6. /**
  7. * 获取运算结果
  8. * @param numA 数值A
  9. * @param numB 数值B
  10. * @param operate 运算符
  11. * @return
  12. */
  13. public static double getResult(double numA, double numB, String operate) {
  14. double result = 0L;
  15. switch (operate) {
  16. case "+":
  17. result = numA + numB;
  18. break;
  19. case "-":
  20. result = numA - numB;
  21. break;
  22. case "*":
  23. result = numA * numB;
  24. break;
  25. case "/":
  26. result = numA / numB;
  27. break;
  28. default:
  29. break;
  30. }
  31. return result;
  32. }
  33. }
  1. /**
  2. * 测试类
  3. * Created by callmeDevil on 2019/5/26.
  4. */
  5. public class Test {
  6. public static void main(String[] args) {
  7. Operation operation = new Operation();
  8. double numA = 10;
  9. double numB = 2;
  10. System.out.println("加法:" + operation.getResult(numA, numB, "+"));
  11. System.out.println("减法:" + operation.getResult(numA, numB, "-"));
  12. System.out.println("乘法:" + operation.getResult(numA, numB, "*"));
  13. System.out.println("除法:" + operation.getResult(numA, numB, "/"));
  14. }
  15. }

但是这样就有个问题,如果这个计算器还需要实现开根号运算呢?难道就直接在Operation类添加一个switch分支就行了吗?不是的,这样会让原来良好运行的代码产生变化,风险太大,因此需要将各种运算的逻辑分离开来,此处引入简单工厂模式

简单工厂模式实现

定义

又称为静态工厂模式,根据工厂类传入的参数动态决定创建某种类(这些类都继承自同一父类或实现同一接口)的实例。

UML图

结合代码有注释

  1. /**
  2. * 运算基础类
  3. * Created by callmeDevil on 2019/5/26.
  4. */
  5. public class BaseOperation {
  6. private double numA;
  7. private double numB;
  8. // 此处省略get、set方法
  9. /**
  10. * 获取结果
  11. * @return
  12. */
  13. public double getResult() {
  14. double result = 0L;
  15. return result;
  16. }
  17. }
  1. /**
  2. * 加法运算
  3. * Created by callmeDevil on 2019/5/26.
  4. */
  5. public class OperationAdd extends BaseOperation {
  6. @Override
  7. public double getResult() {
  8. return getNumA() + getNumB();
  9. }
  10. }
  1. /**
  2. * 减法运算
  3. * Created by callmeDevil on 2019/5/26.
  4. */
  5. public class OperationSub extends BaseOperation {
  6. @Override
  7. public double getResult() {
  8. return getNumA() - getNumB();
  9. }
  10. }
  1. /**
  2. * 乘法运算
  3. * Created by callmeDevil on 2019/5/26.
  4. */
  5. public class OperationMul extends BaseOperation {
  6. @Override
  7. public double getResult() {
  8. return getNumA() * getNumB();
  9. }
  10. }
  1. /**
  2. * 除法运算
  3. * Created by callmeDevil on 2019/5/26.
  4. */
  5. public class OperationDiv extends BaseOperation {
  6. @Override
  7. public double getResult() {
  8. if (getNumB() == 0){
  9. throw new RuntimeException("除数不能为0!");
  10. }
  11. return getNumA() / getNumB();
  12. }
  13. }
  1. /**
  2. * 测试类
  3. * Created by callmeDevil on 2019/5/26.
  4. */
  5. public class Test {
  6. public static void main(String[] args) {
  7. // 实现其他运算只需要更改输入的运算符即可
  8. BaseOperation operation = OperationFactory.createOperation("+");
  9. operation.setNumA(10);
  10. operation.setNumB(2);
  11. System.out.println("加法:" + operation.getResult());
  12. }
  13. }

相比普通实现方式的好处

将每种运算的具体实现分离在不同的类中,工厂类只需要负责根据输入的运算符来创建对应的运算类实例即可。比如要一个开方运算是吧,那么需要创建一个开方运算类,同样继承BaseOperation,接着在工厂类中switch中添加一个case分支,然后客户端便能够跟其他运算一样调用。
可能有人会问,这里不也同样是修改了switch分支条件吗?有什么区别?问得好,说明有思考过,但是原因也很明显,要仔细想想。把四种基础运算具体实现分离出去,工厂类中就包含了四行创建实例的代码,这时修改了switch分支的风险,和普通实现方式的风险相比,哪个大已经不用细说了吧。

总结

这里案例代码比较简单,所以看起来会非常明朗,想必不必多说读者应该也能稍有体会。假如每个类型的运算非常复杂,甚至与其他模块关联,那使用设计模式的好处就体现出来了,比起全部代码堆在一个switch case上,在单独的一个类里面会更好维护和扩展吧?想做到完全不修改switch的代码是不可能,最重要的是我们达到了松耦合、可复用、可扩展目的,同时还降低了风险,有何不可。

原文链接:http://www.cnblogs.com/call-me-devil/p/10926633.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号