之前verilog写多了,老是想着if else要完整,否则会产生锁存器。发现现在写代码潜意识里也有这种想法,好逗。。。最近正好看到公司大牛重构代码,优化for循环和if语句,还看到《阿里巴巴Java开发手册》里控制语句里的部分内容,搜了一下发现了《重构 改善既有代码的设计》这本书,发现挺有意思。
卫语句
《阿里巴巴Java开发手册》讲到了卫语句。
《重构 改善既有代码的设计》也讲到了这一点。
Replace Nested Conditional with Guard Clauses
以卫语句取代嵌套条件表达式
对于特殊的不常见的行为或者异常行为,如果将其写入if else的语句中,逻辑就会显得特别复杂。将判断这些情况的条件单独列出来进行检查,如果为真就返回或者抛出异常。这样的单独检查被称为“卫语句”。
这样的代码强调出来某些异常情况,并且和正常的情况进行了分离,更易于理解。如果上面的语句不使用卫语句,就要写成下面的形式,显得不够清晰。
public void today() {
if (isBusy()) {
System.out.println(“change time.”);
}
else if (isFree()) {
System.out.println(“go to travel.”);
}
else {
System.out.println(“stay at home to learn Alibaba Java Coding Guidelines.”);
}
return;
}
以多态取代表达式
如果一个类的行为受类型码控制,即出现switch语句或if eles语句,根据不同的值来执行不同的动作。针对这种情况,可以使用以子类取代类型码的方法,以类型码的宿主类为基类,针对每一种类型码建立一个子类,使用具有多态行为的继承体系。
以一个Power Manager类为例,其根据不同的mode,来设置A、B、C 三种模式,在set方法中判断了mode,并调用了相应的方法setA、setB、setC。
代码如下:
public class PowerManager {
public enum MODE {
A, B, C
}
private MODE mode;
PowerManager(MODE mode) {
this.mode = mode;
}
public void set() {
if (mode == MODE.A)
setA();
else if (mode == MODE.B)
setB();
else if (mode == MODE.C)
setC();
else {
System.out.printf("no such mode: %s", mode.toString());
throw new RuntimeException();
}
}
public void setA() {
System.out.printf("setA");
}
public void setB() {
System.out.printf("setB");
}
public void setC() {
System.out.printf("setC");
}
}
为类型码的每个数值建立相应的类,将基类中的set变为抽象方法,并在各子类中实现。
class PowerManagerNewA extends PowerManagerNew{
PowerManagerNewA() {
}
public void set() {
System.out.printf("setA");
}
}
基类构造函数接受了类型码作为参数,需要将其换为工厂函数,令其返回合适的对象。
public abstract class PowerManagerNew {
public static enum MODE {
A, B, C
}
PowerManagerNew() {
}
abstract void set();
static public PowerManagerNew create(MODE mode) {
switch(mode) {
case A: return new PowerManagerNewA();
case B: return new PowerManagerNewB();
case C: return new PowerManagerNewC();
default: throw new IllegalArgumentException();
}
}
}
类图如下:
在这个例子中并未体现出好处,但是如果基类有很多方法,都是根据类型码来执行相应的动作,就可以体现出来多态的优势。如果增加了新的类型,使用条件表达式,需要查找所有的条件表达式并更新。使用多态,只需要新建一个子类,实现抽象方法,修改基类的create方法即可。
这种方式其实类似于简单工厂,PowerManagerNew是一个工厂接口,工厂根据参数mode来生产A、B、C三种产品。
create是一个静态工厂方法,返回类型是PowerManagerNew,所以可以返回PowerManagerNew类的子类。此外还可以说明一点,抽象类虽然不可以实例化,但是如果具有静态方法,也是可以直接调用的。
以策略模式/状态模式取代类型码
发现代码重构中好多地方用到了设计模式,先留着以后再来填坑。
参考
《重构 改善既有代码的设计》