接口型模式

1. 抽象类和接口之间的区别:
在面向对象的概念中,我们知道所有的对象都是通过类来描绘的,但是反过来却不是 这样。并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类往往用来表征我们在对问题领 域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。

从设计理念层面看abstract class和interface
上面主要从语法定义和编程的角度论述了abstract class和interface的区别,这些层面的区别是比较低层次的、非本质的。本文将从另一个层面:abstract class和interface所反映出的设计理念,来分析一下二者的区别。作者认为,从这个层面进行分析才能理解二者概念的本质所在。
前面已经提到过,abstarct class在Java语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is a"关系,即父类和派生类在概念本质上应该是相同的。对于interface 来说则不然,并不要求interface的实现者和interface定义在概念本质上是一致的,仅仅是实现了interface定义的契约而已。为了使 论述便于理解,下面将通过一个简单的实例进行说明。
考虑这样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示:
使用abstract class方式定义Door:
    abstract class Door {    

abstract void open();

abstract void close();

}

使用interface方式定义Door:
interface Door {    

void open();

void close();

}

其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。
如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢(在 本例中,主要是为了展示abstract class和interface反映在设计理念上的区别
解决方案:
如果我们对于问题领域的理解是:AlarmDoor在概念本质上是Door,同 时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢?前面已经说过,abstract class在Java语言中表示一种继承关系,而继承关系在本质上是"is a"关系。所以对于Door这个概念,我们应该使用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定 义。如下所示:
abstract class Door {    

abstract void open();

abstract void close();

}

interface Alarm {    

void alarm();

}

class AlarmDoor extends Door implements Alarm {    

void open() { … }

void close() { … }

void alarm() { … }

}

这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计 意图。其实abstract class表示的是"is a"关系,interface表示的是"like a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的
使用abstract class方式定义Door:
a 一个类可以实现任意多个接口,但它最多只能继承一个抽象类。
b 一个抽象类可以包含有抽象方法,当然也可以有若干个非抽象方法和属性。但在接口中,无论一个方法是否被显式地声明为抽象的,接口中的方法都是抽象方法,如果有属性则是static final 类型的。
c 抽象类方法的可见性可以是public、protected、private或者修饰符(表示包内可见);而接口方法的可见性修饰符只能是public。
d 抽象类可以定义构造器,而接口不行。
e 继承一个抽象类的各类之间通常具有某种父子关系,而实现某个接口的各个类之间可以没有父子关系。
2

package com.oozinoz.simultation;

public interface RocketSim
{
abstract double getMass();
public double getThrust();
void setSimTime(double t);
}

下面说明正确的是(A,B,D)

A.RocketSim接口中的三个方法都是抽象方法,尽管只有getMass()方法显式地声明为抽象的。
B.RocketSim接口中的三个方法都是公有方法,尽管只有getThrust()方法被显式地声明为公有的。
C.接口被声明为“公有接口”,即使省略了public关键字,它也应该是公有的。
D.可以再创建一个接口,如RocketSimSolid接口,并扩展RocketSim接口。
E.每个接口必须至少含有一个方法。
F.接口可以声明实例字段,实现该接口的类也必须声明此字段。
G.虽然不能实例化一个接口,但接口定义可以声明构造器方法,要求实现该接口的类必须提供具有指定参数的构造器。

答案解析:

接口中的方法总是抽象和公开的,无论是否被显式地声明为abstract及public。

接口的可见性受限于其所在的包,此处可见性修饰符为public,所以com.oozinoz.simulation包之外的其他类可以访问该接口。

一个接口可以扩展另一个接口,如List接口和Set接口都扩展了java.util包中的Collection接口。

不含方法的接口被称为“标记”接口,如Cloneable标记接口。有时候,位于类层次结构高层的方法,如Object.clone()方法,并不适合下面的各个子类。这时,我们可以创建一个标记接口,用于标识哪些子类需要这个方法,哪些子类不需要这个方法。Object类的子类中需要clone()方法的子类可以声明自己实现了Cloneable标记接口。

接口并不能声明实例字段,不过它可以通过声明static和final修饰的字段来声明常量。

接口不可以定义构造器方法。Java接口也无法要求实现它的类提供任何特定的构造器方法。
3 适当地使用Java接口能够简化并完善我们的程序设计,尽管有时候这种设计超出了普通接口的定义和使用方法。

:D 如果期望:将类的外部接口适配客户期望的接口,可应用Adapter模式

:D 如果期望:为一组类提供一个简单的接口,可以使用Facade模式

:D 如果期望:为单个对象和群组对象定义共同的接口,可以使用Composite模式

:D 如果期望:将实现与抽象相分离以便二者独立演化,可以使用Bridge模式

每种设计模式都旨在解决不同环境中的某个问题。面向接口的设计模式通常用于需要对一个类或者一组类的方法的访问方式进行定义或重定义的场合。例如,某个类拥有我们需要的功能,但它的方法名却不满足客户的期望,这时,我们就可以使用Adapter模式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值