为什么引入接口

Java为什么引入接口的概念?

我们以一个例子来讲解,我们知道鱼是属于动物类,这个是无可争议的,但是同样地,鱼被我们抓住之后,它也同样属于食物类,这样的话,鱼类即是动物类又是食物类,那么在Java中的表述就是,鱼类既是食物类的子类,又是动物类的子类,这样是与Java的规则冲突,因为在Java中一个类只能继承一个类,所以引入了接口的概念,一个类可以继承多个接口。
我们运用接口的时候一般会采用六种形式:在这,我们主要以这个来详细说明接口如何运用

  1. 定制服务模式
  2. 适配器模式
  3. 默认适配器模式
  4. 代理模式
  5. 标识类型模式
  6. 常量接口模式

接口的概念

Java中接口有两种意思:

  1. 其一是概念性的接口,即系统对外提供的所有服务,类的所有能被外部使用者访问的方法构成了类的接口
  2. 其二是用interface关键字定义的实实在在的接口,这个就是我们这里要说的接口类型。它用于明确地描述系统对外的服务。
public interface Photographable{
public void takePhoto();//该接口定义了拍照服务
}
public class camera implements Photographable{
public void takePhoto(){}
}
//该代码通过implements关键字实现了拍照功能。

接口中的成员变量和成员方法有很多限制

  1. 接口中的成员变量默认是public static final类型的,必须被显示格式化,并且接口中的成员变量必须是这个类型的。这个很容易理解,因为接口这个类型中的成员变量本来就是要被引用的,所有设置成这种格式。
  2. 接口中的方法默认都是abtract和public 类型的,因为是abstract类型的,所以在接口中只能声明不能实现。
  3. JDK8以前的版本,接口只能包含抽象方法,JDK8以后,可以定义默认方法和静态方法。默认方法用default关键字来声明,默认方法进而静态方法可以在接口中实现,接口的实现类既可以直接访问默认方法也可以覆盖默认方法。
public interface MyIFC{
default void method1(){
System.out.println("Interface default method1");
}
static void method2(){
System.out.println("Interface static method2");
}
}
  1. 接口没有构造方法,所以不能实例化。
  2. 一个接口不能通过implements关键字承接其他接口,但是可以继承多个接口。
  3. 不允许创建接口的实例,但是可以定义接口类型的引用变量,该变量引用实现了这个接口的类的实例。
  Photographable t=new Camera();
  //Photographable是接口类型,Camera是承接接口的类,这里创建了这个引用接口的类的实例。

抽象类和接口的异同

相同之处
  • 代表了系统的抽象层
  • 都不能被实例化
  • 都能包含抽象方法
  • 从JDK8开始,不仅抽象类能为部分方法提供默认实现接口也具有这一特性。
不同之处
  • 接口中的变量只能public 、static 、final类型的,而抽象类中可以定义各种类型的。
  • 一个类只能继承一个直接的父类,这个父类可能是抽象类,一个类可以实现多个接口。

接口的设计模式

前面提到了接口的常用的设计模式,下面我们来讲一下,详细可以参考head first设计模式这本书。那么我们到底该如何设置接口呢?

定制服务模式

当一个系统能对外提供多种类型的服务时,一种方式是设计粗粒度的接口,把所有的服务放在同一个接口里,另一种是设计精粒度的接口,把服务放在不同的接口中,这两种设计方式比较一下,很明显,第一种设计的接口比较臃肿,所以用户都访问一个接口,若这个接口出现问题,那么所有服务都不能使用。第二种设计模式就是,我们可以将服务划分为多个不同的种类,对接口进行严格划分,然后将服务放进接口中。很明显这种服务比较好,比较容易维护。
服务定制好之后,我们如何实现这些服务。为了提高代码的重复性,每个精粒度要足够小,所有首先要为这些精粒度的接口提供实现类。复合接口的实现类同样要承接其他的接口。这是定制服务模式。

适配器模式

适配器是一种转接的方式,就比如说,变压器就是个适配器,他将高电压变到低电压,同样地,我们这里适配器也是起到一种转换的功能。
适配器模式有两种实现方式:

  1. 继承实现方式。
public class SourceImpl implements SourceIFC{
public int add(int a,int b){
return a+b;
}
}
public class TargetImpl extends SourceImpl implements TargetIFC{
public int addOne(int ){

return add(a,1);
}
}

该代码中SourceIFC接口中存在方法add,我们要将方法转接到TargetIFC接口中,这就需要一个适配器,此时的适配器就是TargetImp类。

  1. 组合实现方式
public class TargetImp implements TargetIFC{
private SourceIFC sourceIFC;
public TargetImp(SourceIFC sourceIFC){
this.sourceIFC=sourceIFC;
}
public int add(int a,int b){
return sourceIFC.add(a,b);
}
public int addOne(int a){
return sourceIFC.add(a,1);
}
}

该代码的目的与上面的代码目的一样。都是为了将SourceIFC接口的中方法转接到TargetIFC接口中。两种实现方式的优略各不相同,这涉及到继承方式和组合方式的优略,可以自己查找材料。

默认适配器模式

我们以监听事件接口为例

public interface MouseListener{
//鼠标监听接口定义了很多方法
public void mouseClicked(MouseEvent e);
public void mousePressed(MouseEvent e);
public void mouseExited(MouseEvent e);
}

public class MouseAdapter implements MouseListener{
public void mouseClicked(MouseEvent e){}
public void mousePressed(MouseEvent e){}
public void mouseExited(MouseEvent e){}
}

JDK提供了一个默认适配器MouseAdapte,实现所有方法,均为空的方法体。

//用户通过继承适配器类,来覆盖特定的方法,这就是默认适配器模式
public class MyMouseListener extends MouseAdapter{
public void mousePressed(MouseEvent e){
//按照自己的想法覆盖
}
}
代理模式

这个模式就是通过中间类型来转接。
该设计模式,就是通过一个中间类来对接口的方法进行转接,就比如你要租房子,你自己不行去找房源,你直接通过中间这个中间类来获取房子的类型。该模式比较容易理解。

标识类型模式

该模式同样容易理解,定义一个接口,接口中不写任何方法,任何方法都在实现类中定义

public interface Food{}
public class Fish extends Animal implements Food{
public void feed(Animal animal,Object food){}
}
//定义了一个食物接口,任何承接了这个接口的类都可以做食物

常量接口模式

把软件中常用的一些常量放在一个专门的接口中定义,每个承接这个接口的类都可以调动常量。

public interface MyConstants{
public static final double MATH_PI=3.1415926;
public static final double MATH_PI=2.71828;
}

该接口中定义了两个常量,任何想要调用这两个常量的累,可以直接承接这个接口就可以。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值