使用abstract class方式定义Door: abstract class Door { abstract void open(); abstract void close(); }
用interface方式定义Door: 其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。 如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢(在本例中,主要是为了展示abstract class 和interface 反映在设计理念上的区别,其他方面无关的问题都做了简化或者忽略)?下面将罗列出可能的解决方案,并从设计理念层面对这些不同的方案进行分析。
方案一 : 简单的在Door的定义中增加一个alarm方法,如下: abstract class Door { abstract void open(); abstract void close(); abstract void alarm(); } 或者 interface Door { void open(); void close(); void alarm(); }
那么具有报警功能的AlarmDoor的定义方式如下: class AlarmDoor extends Door { void open(){…} void close(){…} void alarm(){…} } 或者 class AlarmDoor implements Door { void open(){…} void close(){…} void alarm(){…} } 这种方法违反了面向对象设计中的一个核心原则ISP (Interface Segregation Principle),在Door的定义中把Door概念本身固有的行为方法和另外一个概念“报警器”的行为方法混在了一起。这样引起的一个问题是那些仅 仅依赖于Door这个概念的模块会因为“报警器”这个概念的改变(比如:修改alarm方法的参数)而改变,反之依然。
方案二: 既然open、close和alarm属于两个不同的概念,根据ISP原则应该把它们分别定 义在代表这两个概念的抽象类中。定义方式有:这两个概念都使用 abstract class 方式定义;两个概念都使用interface方式定义;一个概念 使用 abstract class 方式定义,另一个概念使用interface方式定义。