文/沉默王二

曹操在《短歌行》中为杜康酒打过一个价值一亿个亿的广告——“何以解忧,唯有杜康”,我替曹操感到惋惜的是他本人并不会收到这笔不菲的代言费。想一想,要是三国时期的明星人物们有这个代言意识的话,保证各家的军费收入会多出来一个重量级的来源。

不过,酒真的能解忧吗?我不大敢相信。李白就曾质疑过:“举杯消愁愁更愁,抽刀断水水更流。”我和李白持相同的观点,酒啊,真的不容易解忧,但绝对可以增加作者莫名的写作冲动。

我在写本文之前就小酌了一杯,一不小心激发了我强烈的创作欲望。不过我要奉劝各位,寒冬之际,如果遇到烦心事,千万别肆意地追求一醉方休,万事要懂得适可而止

01 抽象类

一种比较苍白的说法是:在Java中,通过关键字abstract定义的类叫做抽象类。Java是一门面向对象的语言,因此所有的对象都是通过类来描述的;但反过来,并不是所有的类都是用来描述对象的,抽象类就是其中的一种。

以下示例展示了一个简单的抽象类:

// 个人认为,一名教练必须攻守兼备
abstract class Coach {public abstract void defend();public abstract void attack();
}
复制代码

在一个抽象类中,至少有一个抽象方法(通过关键字abstract定义的方法,并且没有方法体,如上例中的defend()方法和attack()方法),否则就没有必要称之为抽象类。需要注意的是,抽象类是不能实例化的! 它需要被一个子类继承,就像以下示例那样。

abstract class Coach {public abstract void defend();public abstract void attack();
}class Hesai extends Coach {@Overridepublic void defend() {System.out.println("防守赢得冠军");}@Overridepublic void attack() {System.out.println("控球是把双刃剑");}
}public class Demo {public static void main(String[] args) {Coach moliniao = new Hesai();moliniao.defend();moliniao.attack();}
}
复制代码

我们都知道,一个好的教练,必须攻守兼备,但每个教练的进攻理念和防守理念不尽相同。因此,我在教练这个抽象类(Coach)中定义两个抽象方法,一个进攻(attack)一个防守(defend),这两个方法的具体实现都要由抽象类的子类确定,抽象类本身并不负责。

我们也都知道,何塞·穆里尼奥是足球界的顶级教练。他是我最爱的足球教练,没有之一。尽管他在曼联的失败有他自身的原因,但我依然崇拜他,因为:“请不要说我傲慢,因为我只是实话实说,我是欧洲冠军,因此我并非籍籍无名,而是特殊的一个!”他是固执的反控球主义者,坚信控球是把双刃剑,防守赢得冠军。

好了,对于抽象类我们简单总结一下:

1、抽象类不能被实例化。 2、抽象类应该至少有一个抽象方法,否则它没有任何意义。 3、抽象类中的抽象方法没有方法体。 4、抽象类的子类必须给出父类中的抽象方法的具体实现,除非该子类也是抽象类。

02 接口

我们知道,有抽象方法的类被称为抽象类,也就意味着抽象类中还能有不是抽象方法的方法。这样的类就不能算作纯粹的接口,尽管它也可以提供接口的功能——只能说抽象类是普通类与接口之间的一种中庸之道。

接口(英文:Interface),在Java中是一个抽象类型,是抽象方法的集合;接口通过关键字interface来定义。接口与抽象类的不同之处在于:

1、抽象类可以有方法体的方法,但接口没有。 2、接口中的成员变量隐式为static final,但抽象类不是的。 3、一个类可以实现多个接口,但只能继承一个抽象类。

以下示例展示了一个简单的接口:

// 隐式的abstract
interface Coach {// 隐式的publicvoid defend();void attack();
}
复制代码

接口是隐式抽象的,所以声明时没有必要使用abstract关键字;接口的每个方法都是隐式抽象的,所以同样不需要使用abstract关键字;接口中的方法都是隐式public的。

和抽象类一样,接口也不能直接被实例化,它需要一个类来实现它,就像以下示例展示那样。

class Hesai implements Coach {@Overridepublic void defend() {System.out.println("防守赢得冠军");}@Overridepublic void attack() {System.out.println("控球是把双刃剑");}
}public class Demo2 {public static void main(String[] args) {Coach moliniao = new Hesai();moliniao.defend();moliniao.attack();}
}
复制代码

实现一个接口需要用到关键字implements,它表示:“我这个类遵从了接口的协议,如果你想使用我,看接口就行了,具体实现不用关心。”

03 多重实现

在现实生活中,何塞·穆里尼奥不止是一名足球教练,他还是一个值得被尊重的英雄——凭借自身的努力,他从一名籍籍无名的跟班翻译,逐渐蜕变为一名家喻户晓的顶级教练。

如果要在程序的世界里体现何塞·穆里尼奥的多重角色,就可以使用接口,就像以下示例展示那样。

package com.cmower.java_demo.nine.inf;interface Coach {// 隐式的publicvoid defend();void attack();
}interface Hero {void fight();
}class Hesai implements Coach, Hero {@Overridepublic void defend() {System.out.println("防守赢得冠军");}@Overridepublic void attack() {System.out.println("控球是把双刃剑");}@Overridepublic void fight() {System.out.println("只要一息尚存,就应该战斗到最后");}
}public class Demo2 {public static void defend(Coach coach) {coach.defend();}public static void fight(Hero hero) {hero.fight();}public static void main(String[] args) {Hesai moliniao = new Hesai();defend(moliniao);fight(moliniao);}
}
复制代码

可以看到,创建的Hesai对象可以向上转型为Coach和Hero,然后调用各自接口中实现的具体方法,因为Hesai这个类同时实现了两个接口,分别是Coach和Hero(class Hesai implements Coach, Hero,接口之间通过英文逗号隔开)。

04 接口在应用中常见的三种模式

在编程领域,好的设计模式能够让我们的代码事半功倍。在使用接口的时候,经常会用到三种模式,分别是策略模式、适配器模式和工厂模式。

1)策略模式

策略模式的思想是,针对一组算法,将每一种算法封装到具有共同接口的实现类中,接口的设计者可以在不影响调用者的情况下对算法做出改变。示例如下:

// 接口:教练
interface Coach {// 方法:防守void defend();
}// 何塞·穆里尼奥
class Hesai implements Coach {@Overridepublic void defend() {System.out.println("防守赢得冠军");}
}// 德普·瓜迪奥拉
class Guatu implements Coach {@Overridepublic void defend() {System.out.println("进攻就是最好的防守");}
}public class Demo {// 参数为接口public static void defend(Coach coach) {coach.defend();}public static void main(String[] args) {// 为同一个方法传递不同的对象defend(new Hesai());defend(new Guatu());}
}
复制代码

Demo.defend()方法可以接受不同风格的Coach,并根据所传递的参数对象的不同而产生不同的行为,这被称为“策略模式”。

2)适配器模式

适配器模式的思想是,针对调用者的需求对原有的接口进行转接。生活当中最常见的适配器就是HDMI(英语:High Definition Multimedia Interface,中文:高清多媒体接口)线,可以同时发送音频和视频信号。适配器模式的示例如下:

interface Coach {void defend();void attack();
}// 抽象类实现接口,并置空方法
abstract class AdapterCoach implements Coach {public void defend() {};public void attack() {};
}// 新类继承适配器
class Hesai extends AdapterCoach {public void defend() {System.out.println("防守赢得冠军");}
}public class Demo {public static void main(String[] args) {Coach coach = new Hesai();coach.defend();}
}
复制代码

Coach接口中定义了两个方法(defend()和attack()),如果类直接实现该接口的话,就需要对两个方法进行实现。

如果我们只需要对其中一个方法进行实现的话,就可以使用一个抽象类作为中间件,即适配器(AdapterCoach),用这个抽象类实现接口,并对抽象类中的方法置空(方法体只有一对花括号),这时候,新类就可以绕过接口,继承抽象类,我们就可以只对需要的方法进行覆盖,而不是接口中的所有方法。

3)工厂模式

所谓的工厂模式理解起来也不难,就是什么工厂生产什么,比如说宝马工厂生产宝马,奔驰工厂生产奔驰,A级学院毕业A级教练,C级学院毕业C级教练。示例如下:

// 教练
interface Coach {void command();
}// 教练学院
interface CoachFactory {Coach createCoach();
}// A级教练
class ACoach implements Coach {@Overridepublic void command() {System.out.println("我是A级证书教练");}}// A级教练学院
class ACoachFactory implements CoachFactory {@Overridepublic Coach createCoach() {return new ACoach();}}// C级教练
class CCoach implements Coach {@Overridepublic void command() {System.out.println("我是C级证书教练");}}// C级教练学院
class CCoachFactory implements CoachFactory {@Overridepublic Coach createCoach() {return new CCoach();}}public class Demo {public static void create(CoachFactory factory) {factory.createCoach().command();}public static void main(String[] args) {// 对于一支球队来说,需要什么样的教练就去找什么样的学院// 学院会介绍球队对应水平的教练。create(new ACoachFactory());create(new CCoachFactory());}
}
复制代码

有两个接口,一个是Coach(教练),可以command()(指挥球队);另外一个是CoachFactory(教练学院),能createCoach()(教出一名优秀的教练)。然后ACoach类实现Coach接口,ACoachFactory类实现CoachFactory接口;CCoach类实现Coach接口,CCoachFactory类实现CoachFactory接口。当需要A级教练时,就去找A级教练学院;当需要C级教练时,就去找C级教练学院。

依次类推,我们还可以用BCoach类实现Coach接口,BCoachFactory类实现CoachFactory接口,从而不断地丰富教练的梯队。

05 总结

尽管接口使得抽象更进一步,但任何抽象性都应该根据真正的需求而产生,因此恰当的原则是优先选择类而不是接口,只有在真正需要接口的时候再重构代码。

Java接口的实例应用:致敬我的偶像——何塞·穆里尼奥相关推荐

  1. 前端vue后端java,Vue调用后端java接口的实例代码_亦心_前端开发者

    前段时间 做了个学校的春萌项目,其中用到 先上后端接口代码: package controller; import net.sf.json.JSONObject; import util.DBUtil ...

  2. vue.js 调用java_Vue.js调用后端java接口的实例代码

    Vue.js调用后端java接口的实例代码 发布于 2020-11-30| 复制链接 分享一篇关于Vue调用后端java接口的实例代码,具有很好的参考价值,希望对大家有所帮助.一起跟随小妖过来看看吧 ...

  3. java接口的实例:打印工资单

    import java.util.Scanner; /** 工资:基本工资,加班补助,奖金* 扣除:养老保险,医疗保险,还有超过5000的收个人所得税的3%* * * * **/ public cla ...

  4. java接口和实例_java – 接口和实例化

    第二个声明是错误的: Then it goes on and says a paragraph or so later that "You can declare a variable to ...

  5. Java 接口基础详解,java开发面试笔试题

    我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...

  6. Java的接口及实例

    一.定义 Java接口(Interface),是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为( ...

  7. 通过实例讲解java接口和抽象类的特殊实现方法

    一.java中的接口本质上是加约束的抽象类 //抽象类 public abstract class AExample { public abstract int add(int x,int y): p ...

  8. Java的接口及实例(转)

    转自:http://blog.csdn.net/liujun13579/article/details/7736116 一.定义 Java接口(Interface),是一系列方法的声明,是一些方法特征 ...

  9. java判断接口对象是哪个子类_Java提供了一个关键字( ),可以判断一个对象是否为某个类(或接口)的实例或者子类实例。...

    Java提供了一个关键字( ),可以判断一个对象是否为某个类(或接口)的实例或者子类实例. 更多相关问题 -Do you know a has just opened in our neighborh ...

最新文章

  1. Python标准库——collections模块的Counter类
  2. 14,matlab中如何查看程序中所调用的函数
  3. phpmyadmi 上传大文件
  4. xfce4面板消失了解决方案+xfce4的面板保存设置以及读取
  5. 结构体变量和结构体指针变量作为函数参数传递问题
  6. 如何解除FSO上传程序小于200k限制?
  7. Hadoop HIVE 复合数据类型
  8. 决策树CART算法讲解
  9. 学一下HDFS,很不错(大数据技术原理及应用)
  10. Command line is too long. Shorten command line for Doc.generateAsciiDocs or
  11. Windows 2003 网络负载均衡的详细配置文档
  12. 使用dsoframer演示ppt
  13. 【安卓】3.修改列表增加下划线样式(保姆级图文+附示例)
  14. 输入日期判断这一年的第几天
  15. 51单片机 YF-S201水流量检测传感器的使用
  16. 解决win10开机内存过高的办法(亲测有效)
  17. 【BSV动态】VXPASS与世卫组织合作为莱索托提供数字疫苗监测服务
  18. 脑电波也能卖萌 这样的传感器好特别
  19. element的el-input-number的默认值的问题
  20. java中的码点_Java中码点和码点单元 码点与字符串的互化

热门文章

  1. 小程序判断一个对象是否为空 length不为0的空对象(空集合list)
  2. html div 区域,div全称division,意为“区分”。div标签被称为区隔标签,表示一块可显示 HTML 的区域。DIV的主要属性有(     )...
  3. MomentJs 常用api
  4. 雅腾php怎么样_2018年09月26日
  5. 用递归实现求n!阶层和菲波那切数列
  6. 基于JQuery 改造bootstrap模态框拖动功能
  7. Win32汇编:过程与宏调用
  8. 监控系统zabbix
  9. CSS参考手册_web前端开发参考手册系列
  10. 限制7种范围IP的ASP自定义函数(改进)