面试官 :有如下的代码,如何去除代码中的if?
public int calculate(int a, int b, String action) { if ("ADD".equals(action)) { return a + b; } if ("MUL".equals(action)) { return a * b; } if ("DIV".equals(action)) { return a / b; } if ("SUB".equals(action)) { return a - b; } throw new RuntimeException("action unknown"); }
小白 :巴拉巴拉写了一堆代码,代码如下:
public interface Calculator { int execute(int a, int b); } public class Addition implements Calculator { @Override public int execute(int a, int b) { return a + b; } } public class Subtraction implements Calculator { @Override public int execute(int a, int b) { return a - b; } } public class Multiplication implements Calculator { @Override public int execute(int a, int b) { return a * b; } } public class Division implements Calculator { @Override public int execute(int a, int b) { return a / b; } } public class CalculatorHolder { private static Map<String, Calculator> calculatorMap = new HashMap<>(); static { calculatorMap.put("ADD", new Addition()); calculatorMap.put("SUB", new Subtraction()); calculatorMap.put("MUL", new Multiplication()); calculatorMap.put("DIV", new Division()); } publicstatic Calculator getCalculator(String action) { return calculatorMap.get(action); } } # 使用 CalculatorHolder.getCalculator( "ADD").execute(1,2); CalculatorHolder.getCalculator( "MUL").execute(1,2);
面试官 :你的这种解决方案,有人说使用了工厂模式,你觉得是吗?
小白 :不是,真正的工厂模式有两种:工厂方法和抽象工厂。工厂方法使用继承,首先定义一个抽象父类工厂,然后定义子类工厂,把工厂要创建的对象委托给子工厂类,子工厂类实现父工厂类中要创建对象的方法。抽象工厂使用对象组合,首先定义一个工厂接口,然后定义工厂接口实现类,在实现类中实现接口的方法来创建对象,最后使用组合将接口实现类注入到要创建对象的地方。还有一种是简单工厂,但它不能算是真正意义上的设计模式,就是通过ifelse方式实现的。
面试官 :你觉得工厂模式有什么优缺点?
小白 :优点就是扩展容易,也不用再修改以前的代码,新增对象创建工厂即可,减少对象创建的依赖和强耦合。缺点就是会产生很多的工厂类或对象类,管理上会麻烦些,代码变的更多了。
面试官 :你刚刚的这种解决方案,如果对象的生命周期是由Spring容器来管理的,也就是bean的实例化是在Spring容器启动时发生的,如何将Addition这种对象实例注入到calculatorMap中?
小白 :有两种方式,一种是将calculatorMap中的key和value(bean的id)配置到Spring的xml声明文件中,另一种是通过编码的方式,自定义一个类实现Spring的ApplicationContextAware接口和InitializingBean接口,在类中声明属性一个ApplicationContext,通过setApplicationContext将这个属性指向Spring容器中的应用上下文ApplicationContext对象,然后实现afterPropertiesSet方法,通过applicationContext.getBeansOfType(Calculator.class)获取Calculator接口的所有实现类,结果是一个Map,key是bean的name,value是bean的实例对象,然后遍历这个Map,将元素注入到calculatorMap中。
面试官 :你还能用其它 设计模式 去除if吗?
小白 :策略模式。
面试官 :说一下你理解的策略模式?
小白 :在运行时,通过不同的策略(创建或引用不同的对象)改变类的行为,其实就是根据实现类的不同,动态的调用不同类的相同方法。
面试官 :能不能写一下具体代码?
小白 :一顿操作,霹雳吧啦,代码如下:
public class CalculatorHolder { private Calculator calculator; public CalculatorHolder(Calculator calculator) { this.calculator = calculator; } public int execute(int a, int b){ return calculator.execute(a, b); } } CalculatorHolder ch = new CalculatorHolder(new Addition()); ch.execute(1, 2); ch = new CalculatorHolder(new Subtraction()); ch.execute(1, 2);
面试官 :策略模式有什么优缺点?
小白 :优点就是可以解决像ifelse这样的不好维护的代码,做到对扩展开放、对修改关闭。缺点就是也会产生很多像Addition等这样的代码,导致类膨胀。
面试官 :你刚刚说到开闭原则,设计模式还有其它什么原则?
小白 :里氏替换原则,任何基类可以出现的地方,子类一定可以出现;依赖倒置原则,面向接口编程,依赖于抽象而不依赖于具体实现;单一职责原则,一个类应该只负责一项职责,做到职责单一;迪米特法则,一个对象应该对其它对象保持最少的了解;接口隔离原则,类和类之间应该建立在最小接口上。
面试官 :解释一下接口隔离原则的内容?
小白 :......巴拉巴拉......
推荐阅读:
高并发编程-ExecutorCompletionService深入解析
如有收获,请点击底部右下角" 在看 ",谢谢!
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 如何去除代码中的多次 if 而引发的一连串面试问题
- 利用柯里化去除重复代码
- iOS去除Xcode代码警告
- 如何去除讨厌的Chrome自动填充黄色背景
- 编译原理学习一,去除代码中的注释
- iOS 去除 Webview 键盘顶部工具栏
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
高效前端:Web高效编程与优化实践
李银城 著 / 机械工业出版社 / 2018-3-15 / 89.00元
这不是一本单纯讲解前端编程技巧的书,而是一本注重思想提升和内功修炼的书。 全书以问题为导向,精选了前端开发中的34个疑难问题,从分析问题的原因入手,逐步给出解决方案,并分析各种方案的优劣,最后针对每个问题总结出高效编程的最佳实践和各种性能优化的方法。 全书共7章,内容从逻辑上大致可以分为两大类: 第一类,偏向实践,围绕HTML、CSS、JavaScript等传统前端技术,以及PW......一起来看看 《高效前端:Web高效编程与优化实践》 这本书的介绍吧!