以前学习Java的时候,就听过面向接口编程,可惜当时水平太低不理解(当然,现在水平还是很低),现在学习了一点。接下来,我们通过一个小例子学习面向接口编程。
背景:假设每个单身狗都喜欢和蚊子玩,蚊子有一个唱歌的方法。代码如下:
//Mosquito.java
//蚊子类,拥有一个唱歌的方法
package project.app.service;
publicclassMosquito{
publicString sing(){
return"You have to admit that I sing songs very well.";
}
}
//Single.java
//单身狗类,playWithMosquito依赖于蚊子类
package project.app.service;
import project.app.service.Mosquito;
publicclassSingle{
privateMosquito mosquito;
publicvoid setMosquito(Mosquito mosquito){
this.mosquito = mosquito;
}
publicvoid playWithMosquito(){
System.out.println(mosquito.sing());
}
}
接下来,可以测试一下
//Test.java
package chris;
import project.app.service.*;
publicclassTest{
publicstaticvoid main(String[] args)throwsException{
Single single =newSingle();
Mosquito mosquito =newMosquito();
//设置single实例和mosquito实例的关系
single.setMosquito(mosquito);
single.playWithMosquito();
}
}
结果:
You have to admit that I sing songs very well.
如果之后单身狗和蚊子友谊的小船翻了,改成和蟑螂玩了,应该怎么改代码呢?一般的做法大概是这样。
增加蟑螂类。
//Cockroach.java
//蟑螂类,有不同于蚊子的唱歌的方法
package project.app.service;
publicclassCockroach{
publicString sing(){
return"I sing when everybody is in sleep.";
}
}
在单身狗类中,将有关蚊子的改成有关蟑螂的。
- //Single.java
//单身狗类,playWithMosquito依赖于蟑螂类
package project.app.service;
import project.app.service.Cockroach;
publicclassSingle{
privateCockroach cockroach;
publicvoid setCockroach(Cockroach cockroach){
this.cockroach = cockroach;
}
publicvoid playWithCockroach(){
System.out.println(cockroach.sing());
}
}
可以测试一下。
//Test.java
package chris;
import project.app.service.*;
publicclassTest{
publicstaticvoid main(String[] args)throwsException{
Single single =newSingle();
Cockroach cockroach =newCockroach();
single.setCockroach(cockroach);
single.playWithCockroach();
}
}
运行结果: I sing when everybody is in sleep.
经过上面的实践,我们发现,单身狗类依赖于蚊子类,导致蚊子类变化成蟑螂类时,单身狗类的代码必须跟着改变,这样类之间的耦合性太强了。我们想想,蚊子和蟑螂虽然唱着不同的歌,但是唱歌的方法却是相同的。为了代码能够降低耦合,我们可以使用接口,利用面向对象的多态性。可以将蚊子和蟑螂抽象一下,在概念上,往上升一级,比如宠物,动物,生物,物质。动物、生物和物质这几个接口就太宽了,也把单身狗包括进去了,那么,我们选择到宠物这一层。我们通过例子看一下。
//Pet.java
//宠物接口,有一个唱歌的方法
package project.app.service;
publicinterfacePet{
publicString sing();
}
蚊子类实现宠物接口
//Mosquito.java
//
package project.app.service.impl;
import project.app.service.Pet;
publicclassMosquitoimplementsPet{
publicString sing(){
return"You have to admit that I sing songs very well.";
}
}
//Single.java
//单身狗类,playWithMosquito依赖于Pet接口,注意,这个时候单身狗类只依赖于宠物接口,不依赖于具体的蚊子类了。
package project.app.service;
import project.app.service.Pet;
publicclassSingle{
privatePet pet;
publicvoid setPet(Pet pet){
this.pet = pet;
}
publicvoid playWithPet(){
System.out.println(pet.sing());
}
}
//Test.java
package chris;
import project.app.service.Single;
import project.app.service.Pet;
import project.app.service.impl.Mosquito;
publicclassTest{
publicstaticvoid main(String[] args)throwsException{
Single single =newSingle();
Mosquito mosquito =newMosquito();
single.setPet(mosquito);
single.playWithPet();
}
}
如果我们改成和蟑螂玩,则修改代码时,增加蟑螂类的代码(也要实现宠物接口),单身狗类不用变(耦合性大大降低啊,节省了好多重复劳动)。
//Cockroach.java
//蟑螂类,有唱歌的方法
package project.app.service.impl;
import project.app.service.Pet;
publicclassCockroachimplementsPet{
publicString sing(){
return"I sing when everybody is in sleep.";
}
}
测试代码经过轻微的修改:
//Test.java
package chris;
import project.app.service.Single;
import project.app.service.Pet;
import project.app.service.impl.Cockroach;
publicclassTest{
publicstaticvoid main(String[] args)throwsException{
Single single =newSingle();
Cockroach cockroach =newCockroach();
single.setPet(cockroach);
single.playWithPet();
}
}
上面的例子可以算是面向接口编程的一个例子。通过使用接口,利用面向对象的多态性,将蚊子类抽象成宠物接口,使单身狗类只依赖于抽象的宠物接口,大大降低了单身狗类对具体的蚊子类的依赖。这样,大大地方便了后期的扩展和维护,比如增加会唱歌的蟋蟀类等。