Java中消除实现继承和面向接口的编程(2)
引起上面问题的很重要的原因便是基类和派生类之间的耦合。往往只是对基类做了小小的改动,却不得不重构它们的所有的派生类,这就是臭名昭著的“脆弱的基类”问题。由于类之间的关系是存在的,因此耦合是不可避免的甚至是必要的。但在做OO设计时,当遇到如基类和派生类之间的强耦合关系,我们就要思量思量,是否一定需要继承呢?是否会有其他的更优雅的替代方案呢?如果一定要学究的话,你会在很多书中会看到这样的原则:如果两个类之间是IS-A关系,那么就使用继承;如果两个类之间是Has-A的关系,那么就使用委派。很多时候这条原则是适用的,但IS-A并不能做为使用继承的绝对理由。有时为了消除耦合带来的问题,使用委派等方法会更好地封装实现细节。继承有时会对外及向下暴露太多的信息,在GOF的设计模式中,有很多模式的目的就是为了消除继承。
关于何时采用继承,一个重要的原则是确定方法是否能够共享。比如DAO ,可以将通用的CRUD 方法定在一个抽象DAO 中,具体的DAO 都派生自这个抽象类。严格的说,抽象DAO 和派生的DAO 实现并不具有IS -A 关系,我们只是为了避免重复的方法定义和实现而作出了这一技术上的选择。可以说,使用接口还是抽象类的原则是,如果多个派生类的方法内容没有共同的地方,就用接口作为抽象;如果 多个派生类 的方法含有共同的地方,就用抽象类作为抽象。当这一原则不适用于接口继承,如果出现接口继承,就会相应地有实现继承(基类更多的是抽象类)。
现在说说面向接口编程。在众多的敏捷方法中,面向接口编程总是被大师们反复的强调。面向接口编程,实际上是面向抽象编程,将抽象概念和具体实现相隔离。这一原则使得我们拥有了更高层次的抽象模型,在面对不断变更的需求时,只要抽象模型做的好,修改代码就要容易的多。但面向接口编程不意味着非得一个接口对应一个类,过多的不必要的接口也可能带来更多的工作量和维护上的困难。
相比于继承,OO中多态的概念要更重要。一个接口可以对应多个实现类,对于声明为接口类型的方法参数、类的字段,它们要比实现类更易于扩展、稳定,这也是多态的优点。假如我以实现类作为方法参数定义了
相关新闻>>
- 发表评论
-
- 最新评论 更多>>