代码检查(2)

2. instanceof检查链

这个问题是连续使用if ... else + instanceof检查来判断一个对象的类型,并采取不同的处理逻辑。示例代码如下:

public void method(Fruit fruit) {
  if (fruit instanceof Apple) {
    ...
  }
  else if (fruit instanceof Orange) {
    ...
  }
  else if .....
}

这不是面向对象的方法,完全没有利用到多态的面向对象特性。我相信一个合格的程序员是不会写出这样的编码的,这一般是新手程序员,特别是对面向对象理解不深刻的程序员会犯的毛病。改正的方法就是在Fruit类中增加一个方法,并在Apple、Orange等子类中实现此方法:

public abstract class Fruit {
  public int m();
}

当然,在环境允许的情况下,尽可能使用protected而不是public来定义这个方法。

现在我们来看一个复杂一点的,同样还是instanceof检查的问题,但这个检查只涉及了Fruit诸多子类中的一部分,而其他的子类,行为是一致的。这时候我们需要在Fruit中引入一致行为的实现:

public abstract class Fruit {
  public int m() {
    //一般的实现。
    ...
  }
}

而更加复杂的行为需要对应复杂的设计,通过对具体水果的抽象,可以发现这些水果可以抽象为几个较为一般的类:

public abstract class Fruit {
  public int m(){
    ...
  }
}

public class TypeAFruit extends Fruit {
  public int m(){
    //特定类型的实现。
  }
}

public class TypeBFruit extends Fruit {
  public int m(){
    // 特定类型的实现。
  }
}

...

关于类的继承层次的问题,有一种说法是“原则上”控制在一定的数量之内。一般来说 这个说法是有道理的(特别是对初学者,它可以有效的避免“滥继承”),但不是放之四海皆准的道理,不要把它教条化。

说到继承层次,不得不提到抽象层次。我们总是在一定的抽象层次上解决问题,抽象层次决定了你解决问题的实现的复杂程度。设计以简洁为美,不要把设计复杂化。但简洁并不意味着“少”,简洁的真正涵义是:模型不比模型所表达的事物更加复杂,不要把“本来简单”的东西复杂化,也不要把本来复杂的东西简单化。

我所要表达的是,设计应该是简洁的,但不是“简单”的。“设计应该简单”的说法,是来自翻译的问题,还是来自理解的问题?简单会导向“偷工减料”,而简洁则要求不要在设计中加料(特别是废料)。

一个继承结构有多少层才是合适的?最上层的类或接口对应着“一般概念”,最下层的类一定可以实例化为具体的对象,这中间有多少“层”,就有多少抽象层次。决定抽象层次,也就是决定你的继承层次的原则有二:

  • 客户代码的需要:客户代码是指调用你的类继承层次中的某些类的代码,客户代码需要知道某个层次的细节。此外需要注意的是,客户代码应该尽量使用最上层的“一般概念”。
  • 重用的需要:在具体的不同类中存在相同代码的时候,就要考虑有没有可能进行抽象,形成一个用于重用目的的父类。
类继承层次的设计也不是一成不变的,按照上面这两个原则,当客户代码不再需要某个层次时,或者当重用代码不可能(一般标志就是大量的override)时,就要考虑改变继承体系的设计。


汗,感觉后面有点越扯越远了。。。


instanceof, inheritance, abstraction

你可能感兴趣的:(代码检查(2))