博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
接口型模式/接口和抽象类的区别/案例分析
阅读量:4182 次
发布时间:2019-05-26

本文共 2526 字,大约阅读时间需要 8 分钟。

接口型模式是什么

定义:

类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(){
.......}}

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


上一篇:

下一篇:

转载地址:http://dlrai.baihongyu.com/

你可能感兴趣的文章
OS进程调度及典型调度算法
查看>>
C++操作Mysql数据库/Linux下
查看>>
I/O知识点汇总
查看>>
【C++】jsoncpp的安装与使用
查看>>
[C++11]半同步半异步线程池实现与分析
查看>>
Redis网络库源码浅解
查看>>
TCP半连接与全连接队列及accept建立连接
查看>>
TCP连接的关闭
查看>>
系统级 I/O与缓冲机制
查看>>
[Web Server](一)Tiny Web Server分析
查看>>
内存管理之用户空间
查看>>
FastCGI 协议分析与C语言实现实例
查看>>
Muduo网络库源码分析之定时器的实现
查看>>
C++智能指针的分析与使用
查看>>
Muduo网络库源码分析之Acceptor和TcpServer
查看>>
Muduo网络库源码分析之TcpConnection Class
查看>>
编写网络服务程序的常用编程模型
查看>>
复合&继承关系下的构造和析构
查看>>
Linux交换空间(swap space)
查看>>
Redis 通信协议(protocol)
查看>>