接口型模式/接口和抽象类的区别/案例分析

接口型模式是什么

定义:

类Client的实例instanceClient希望使用另一个对象instanceX提供的服务service,但在设计时我们并不能确定对象instanceX属于那个类,这时我们将instanceX提供的服务service抽象为一个接口serviceProvider,然后让对象instanceClient通过持有接口serviceProvider的实例来使用服务。这种通过接口间接获得服务的解决方案就是接口模式。

接口模式可以是一个接口抽象一个对象提供的服务,也可以是一组接口抽象一群对象的交互。

包括:

适配器模式、外观模式、合成模式、桥接模式。它们本质上都是接口,但是又超越了普通的接口,更为特殊。

好处:
  1. 降低了系统的耦合度(类Client不直接依赖于任何具体的服务提供者,仅依赖于轻量的接口);
  2. 体现了面向对象中的面向接口编程,而不是针对实现编程(但是接口也增加了设计的复杂度);
  3. Java中接口的设计也是对类不能实现多继承的一种补充(一个类可以实现多个接口)。

接口和抽象类的区别

抽象类和接口是Java中提供的两种抽象机制。两者之间有联系也有区别,选择接口和抽象类能反映出对于问题领域本质的理解,对于设计意图的理解是否正确合理。

所有的对象都需要用类描述,但并不是所有的类都用来描述对象。如果一个类中没有足够的信息来描绘一个具体的对象,这样的类就是抽象类。面向对象领域,抽象类主要用来隐藏信息,比如三角形、正方形、长方形可以抽象成形状。

//抽象类
abstract Class Door {
   abstract void open();
   abstract void close();
}
//接口
interface Door {
   void open();
   void close();
}
  1. 方法只有声明没有实现时就是抽象方法,方法需要被abstract修饰。
  2. 抽象方法必须在抽象类中,类也必须被abstract修饰。但抽象类也可以包括非抽象方法,有自己的数据成员,而接口中的方法默认都是abstract、public,只能包括static、final的数据成员,不过一般不定义。
  3. 抽象类不可以被实例化。因为调用抽象方法没有意义,没有函数体。
  4. 抽象类必须被子类覆盖所有的抽象方法,该子类才可以实例化,否则子类还是抽象类。
  5. abstract不能和private(修饰的不能被覆盖,而抽象就是为了覆盖)、static、final共存(final不能被覆盖)。
  6. 抽象类中的方法全是抽象方法的时候,就变成了一个接口(另一种形式)。所以接口在一定程度上也是一种特殊的抽象类(还是有很大区别的),当然接口也不能被实例化(new)。
  7. 抽象类本质上是is-a的关系,所以本质是继承,一个类只能有一个继承关系。接口是like-a关系,所以接口可以多实现。它们反映出的设计理念不同。
  8. 接口中默认的变量是public static final,且必须给其初值,所以其实现类中不能重新定义,也不能改变其值。而抽象类中的变量默认是friendly,其值可以在子类中重新定义,也可以重新赋值。

接口和抽象类案例分析

以上面的门为例,如果我们要添加一个报警的方法alarm()。此时的抽象类和接口就变成了以下:

//抽象类
abstract Class Door {
   abstract void open();
   abstract void close();
   abstract void alarm();
}
//接口
interface Door {
   void open();
   void close();
   void alarm();
}
------------------------------
//实现类:
Class A extends Door{
   void open(){.......}
   void close(){.......}
   void alarm(){.......}
}
Class A implements Door{
   void open(){.......}
   void close(){.......}
   void alarm(){.......}
}

这种定义实现功能肯定没问题,但是违反了接口隔离原则
接口隔离原则(Interface Segregation Principle, ISP):使用多个专门的接口,而不使用单一的总接口,即客户端不应该依赖那些它不需要的接口。每一个接口应该承担一种相对独立的角色,不干不该干的事,该干的事都要干。

这里具体指Door的定义和功能(行为方法)都放到了一起。由于类不能多继承,拆开放到两个抽象类肯定不行。如果放到两个接口功能上没问题,但对问题领域的概念本质理解出现了偏差。A本质上是一个门,同时具有报警的功能。对于Door的概念应是is-a的关系,所以用抽象类定义。
另外A又具有报警功能,说明又能完成报警概念中定义的行为,所以报警概念通过interface定义。

//抽象类
abstract Class Door {
   abstract void open();
   abstract void close();
}
//接口
interface Alarm {
   void alarm();
}
//实现
Class A extends Door implements Alarm{
   void open(){.......}
   void close(){.......}
   void alarm(){.......}
} 

这种实现方式基本上能够反映出我们对于问题领域的理解,正确的揭示我们的设计意图。抽象类和接口有很大的相似性,但是对于他们的选择又往往反映出问题领域中概念本质的理解、对于设计意图的反映是否正确合理。因为它们表现了概念之间的不同的关系(即使都能实现需求的功能)。


上一篇:设计模式是什么
下一篇:适配器模式

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值