接口隔离原则(The Interface-Segregation Principle)强调类的功能要单一,类的功能臃肿增加不必要的耦合,增加代码的脆弱性,还会增加编译依赖。该原则建议将方法分组,达到隔离接口的目的,具体的方法有委托和多重继承。
在Timed Door的例子中,开始的实现是Timed Door继承Door,Door实现Timer Client这个接口,这样Timed Door就可以通过Timer Client这个接口去使用Timer的功能。但这样做会导致Door依赖于Timer Client,而且并不是所有的Door都需要定时功能。所有的继承于Door的子类都需要提供退化的Timeout方法,违反了LSP。
注意,这里的TimerClient是Timer实现的需求,与Door无关。所有使用Timer的类对相当于Timer的client,需要实现TimerClient这个接口,用于Timer time out时调用。
Timer Client at Top of Hierarchy
Door和Timer Client中的接口分别由不同的client使用,既然使用者相互独立,接口也应该独立,因为使用者也会对接口产生影响。我们一般都会考虑接口对使用者的影响,但使用者也会对接口提出更多的要求。比如文中由于door的需求,需要Timer提供带timeOutId的注册接口。但这个接口的变化会导致Door的所有子类代码都需要修改,这个设计的确很糟糕。
接口隔离原则:使用者不应该被逼去依赖它们不使用的方法。
Clients should not be forced to depend on methods that they do not use.
通过委托或多重继承可以避免依赖不使用的方法。一般使用多重继承,因为委托会产生多余的性能和空间的耗用。这里的委托就是说将对TimerClient的实现委托给TimerClientAdapter去做。
TimedDoor例子中通过将定时接口和Door接口隔离,避免了其它Door子类依赖于定时接口。
Multiply inherited Timed Door
Door Timer Adapter
1 public interface TimerClient { 2 public void timeOut(); 3 } 4 5 public class Timer2 extends TimerTask{ 6 7 private TimerClient mTc; 8 private Timer mTimer; 9 10 public void registry(int timeout, TimerClient tc) { 11 mTc = tc; 12 mTimer = new Timer(); 13 mTimer.schedule(this, timeout*1000); 14 } 15 16 @Override 17 public void run() { 18 // TODO Auto-generated method stub 19 mTc.timeOut(); 20 } 21 }