Java接口的实例应用:致敬我的偶像——何塞·穆里尼奥
文/沉默王二
曹操在《短歌行》中为杜康酒打过一个价值一亿个亿的广告——“何以解忧,唯有杜康”,我替曹操感到惋惜的是他本人并不会收到这笔不菲的代言费。想一想,要是三国时期的明星人物们有这个代言意识的话,保证各家的军费收入会多出来一个重量级的来源。
不过,酒真的能解忧吗?我不大敢相信。李白就曾质疑过:“举杯消愁愁更愁,抽刀断水水更流。”我和李白持相同的观点,酒啊,真的不容易解忧,但绝对可以增加作者莫名的写作冲动。
我在写本文之前就小酌了一杯,一不小心激发了我强烈的创作欲望。不过我要奉劝各位,寒冬之际,如果遇到烦心事,千万别肆意地追求一醉方休,万事要懂得适可而止。
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 {
@Override
public void defend() {
System.out.println("防守赢得冠军");
}
@Override
public 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 {
// 隐式的public
void defend();
void attack();
}
接口是隐式抽象的,所以声明时没有必要使用abstract
关键字;接口的每个方法都是隐式抽象的,所以同样不需要使用abstract
关键字;接口中的方法都是隐式public
的。
和抽象类一样,接口也不能直接被实例化,它需要一个类来实现它,就像以下示例展示那样。
class Hesai implements Coach {
@Override
public void defend() {
System.out.println("防守赢得冠军");
}
@Override
public 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 {
// 隐式的public
void defend();
void attack();
}
interface Hero {
void fight();
}
class Hesai implements Coach, Hero {
@Override
public void defend() {
System.out.println("防守赢得冠军");
}
@Override
public void attack() {
System.out.println("控球是把双刃剑");
}
@Override
public 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 {
@Override
public void defend() {
System.out.println("防守赢得冠军");
}
}
// 德普·瓜迪奥拉
class Guatu implements Coach {
@Override
public 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 {
@Override
public void command() {
System.out.println("我是A级证书教练");
}
}
// A级教练学院
class ACoachFactory implements CoachFactory {
@Override
public Coach createCoach() {
return new ACoach();
}
}
// C级教练
class CCoach implements Coach {
@Override
public void command() {
System.out.println("我是C级证书教练");
}
}
// C级教练学院
class CCoachFactory implements CoachFactory {
@Override
public 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接口的实例应用:致敬我的偶像——何塞·穆里尼奥的更多相关文章
- Java 接口基础详解
目录 Java接口示例 实现一个接口 接口实例 实现多个接口 方法签名重叠 接口变量 接口方法 接口默认方法 接口与继承 继承与默认方法 接口与多态性 在Java中,接口是一个抽象类型,有点类似于类, ...
- 转载:Java的接口及实例
转自:http://blog.csdn.net/liujun13579/article/details/7736116/ 一.定义 Java接口(Interface),是一系列方法的声明,是一些方法特 ...
- 转:十九、Java的接口及实例
http://blog.csdn.net/liujun13579/article/details/7736116 一.定义 Java接口(Interface),是一系列方法的声明,是一些方法特征的集合 ...
- Java的接口及实例
一.定义 Java接口(Interface),是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为( ...
- java接口传递数据的实例
我们要讲E类中的数据变化通知A类,这样通过接口F来实现.具体原理就是E的每次数据改变都让其通知接口:而A类继承接口,所以每次E的调用接口都会触发A类的数据更改事件的触发. 首先创建一个类E: publ ...
- java接口
一.定义 Java接口(Interface),是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为( ...
- Java WebService入门实例
Web Services是由企业发布的完成其特定商务需求的在线应用服务,其他公司或应用软件能够通过Internet来访问并使用这项在线服务. Web Service的关键技术和规则: 1.XML:描述 ...
- JAVA上百实例源码以及开源项目
简介 笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级.中级.高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情.执着,对IT的憧憬. ...
- python面向对象进阶 反射 单例模式 以及python实现类似java接口功能
本篇将详细介绍Python 类的成员.成员修饰符.类的特殊成员. 类的成员 类的成员可以分为三大类:字段.方法和特性. 注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存 ...
随机推荐
- 大数据ssh疑点跟踪
相信运维的对ssh免密登陆应该是对这个再清楚不过的吧,由于我们大数据对于安全这方便管控的很严格,单独找一台物理机作为跳板机,其他的机器都必须要从这个跳板机免密登陆,由于机器比较的多,其中dn30这个域 ...
- Codeforces 258D Little Elephant and Broken Sorting (看题解) 概率dp
Little Elephant and Broken Sorting 怎么感觉这个状态好难想到啊.. dp[ i ][ j ]表示第 i 个数字比第 j 个数字大的概率.转移好像比较显然. #incl ...
- hbase 性能优化 (转载)
一.服务端调优 1.参数配置 1).hbase.regionserver.handler.count:该设置决定了处理RPC的线程数量,默认值是10,通常可以调大,比如:150,当请求内容很大(上MB ...
- Docker 学习2 Docker基础用法
一.docker架构 1.client端 2.server端,docker daemo守护进程,监听在套接字之上.docker支持三种类型套接字. a.ip vs套接字:即IP + 端口套接字 b.i ...
- sublime text 3 package Install 安装失败解决方法
失败原因为官网地址被墙,导致channel_v3文件无法访问. 解决方法: 点击Preferences——>Package Settings——>Package Control——> ...
- angular 数据双向绑定的终极奥义
1.ng-app: 是ng的入口,表示当前元素的所有指令都会被angular管理,让anguar认识这段代码,告诉angular要去管理下面的代码:同时angular执行这段代码的时候会在内部开辟一块 ...
- linux系统,关于Python多版本共存
http://www.cnblogs.com/Yiutto/p/5962906.html 给个地址直接看八~
- 展开被 SpringBoot 玩的日子 《 二 》 WEB 开发
上篇文章介绍了Spring boot初级教程 :< spring boot(一):入门篇 >,方便大家快速入门.了解实践Spring boot特性:本篇文章接着上篇内容继续为大家介绍spr ...
- Git SSL公钥密钥生成
下面教大家简单易懂的五步配置好密钥 第一次配置ssh 和ssl git config --global --list 查看git的配置 步骤: 1. git config --global user. ...
- oracle 报错无法从套接字获取更多数据
报错信息如下: ---查看_optimizer_join_elimination_enabled参数值 切换sys用户 select a.ksppinm name, b.ksppstvl value, ...