接口的定義與使用

抽象類與普通類相比最大的特點(diǎn)是約定了子類的實(shí)現(xiàn)要求,但是抽象類有一個缺點(diǎn):單繼承局限,如果要想約定子類的實(shí)現(xiàn)要求以及避免單繼承的局限就需要使用接口。在你以后的開發(fā)設(shè)計(jì)之中:接口優(yōu)先。在一個操作既可以使用抽象類又可以使用接口的時(shí)候,請優(yōu)先考慮接口。

一. 接口的基本概念

接口就是一個抽象方法和全局常量的集合,在Java中接口可以使用interface關(guān)鍵字來進(jìn)行定義。如果子類要想使用接口,那么就必須利用implements關(guān)鍵字來實(shí)現(xiàn)接口,同時(shí)一個子類可以同時(shí)實(shí)現(xiàn)多個接口,也就是說可以利用接口來實(shí)現(xiàn)多繼承的概念。對于接口的子類(如果不是抽象類)則必須覆寫接口中的全部抽象方法。隨后可以利用子類對象的向上轉(zhuǎn)型通過實(shí)例化子類來得到接口的實(shí)例化對象。

當(dāng)一個子類繼承了多個接口之后,并且接口對象通過子類進(jìn)行實(shí)例化,那么這多個父接口之間是允許互相轉(zhuǎn)換的。

二. 接口使用限制

1. 接口定義完成之后,就需要對其有一個核心的說明,那么首先需要說明的是:接口里面只允許存在有public權(quán)限,也就是說不管是屬性還是方法其權(quán)限只能是public。

在以后編寫接口的時(shí)候,99%的接口里面只會提供有抽象方法,很少在接口里面看見有許多的全局常量。所以很多時(shí)候?yàn)榱朔乐贡苊庖恍╅_發(fā)者出現(xiàn)混亂,所以接口的方法上往往都會加上pubLic。

2. 當(dāng)一個子類需要實(shí)現(xiàn)接口又需要繼承抽象類的時(shí)候,請先使用extends繼承一個抽象類,而后再使用implements實(shí)現(xiàn)多個接口。

3. 一個抽象類可以使用implements實(shí)現(xiàn)多個接口,但是接口不能夠去繼承抽象類。

4. 一個接口可以使用extends來繼承多個父接口。

5. 接口可以定義一系列的內(nèi)部結(jié)構(gòu),包括:內(nèi)部的普通類、內(nèi)部抽象類、內(nèi)部接口,其中使用static定義的內(nèi)部接口就相當(dāng)于一個外部接口。

對于內(nèi)部的結(jié)構(gòu)依然不是你們的首選,而且要想清楚接口的實(shí)際開發(fā)意義,需要大量的項(xiàng)目來驗(yàn)證。

三. 使用接口定義標(biāo)準(zhǔn)

對于接口在實(shí)際的開發(fā)之中有三大核心應(yīng)用環(huán)境:

①定義操作標(biāo)準(zhǔn);

②表示能力;

③在分布式開發(fā)之中暴露遠(yuǎn)程服務(wù)方法。


class TestDemo {

public static void main(String args[]) {

Computer com = new Computer() ;

com.plugin(new Flash()) ;

com.plugin(new Print()) ;

}

}

interface USB {

public void setup() ;? // 安裝USB驅(qū)動

public void work() ;? // 進(jìn)行工作

}

class Computer {

public void plugin(USB usb) {//只能夠插入U(xiǎn)SB設(shè)備

usb.setup() ;

usb.work() ;

}

}

class Flash implements USB {

public void setup() {

System.out.println("安裝U盤驅(qū)動!") ;

}

public void work() {

System.out.println("進(jìn)行數(shù)據(jù)傳輸!") ;

}

}

class Print implements USB {

public void setup() {

System.out.println("安裝打印機(jī)驅(qū)動!") ;

}

public void work() {

System.out.println("進(jìn)行文件打印!") ;

}

}

發(fā)現(xiàn)使用接口和對象多態(tài)性的概念結(jié)合之后,對于參數(shù)的統(tǒng)一更加明確了。而且可以發(fā)現(xiàn)接口是在類之上的設(shè)計(jì)抽象。

四. 工廠設(shè)計(jì)模式(Factory) ?【重點(diǎn)】

首先來看一個簡單的程序范例: 在進(jìn)行類設(shè)計(jì)的時(shí)候,要求首先需要有接口,而后接口要通過子類才可以進(jìn)行對象的實(shí)例化處理。

此時(shí)的程序?qū)崿F(xiàn)的關(guān)鍵是:“IFruit fruit = new Apple() ;”,如果沒有此語句,接口對象將無法進(jìn)行實(shí)例化的操作處理。但是最大的敗筆也在此。主方法是一個客戶端,那么對于程序的修改不應(yīng)該影響到客戶端。

這個時(shí)候new是整個開發(fā)過程之中最大的耦合元兇,而我們在開發(fā)之中要想進(jìn)行解耦合的關(guān)鍵就在于要引入一個第三方,所以這個類可以使用Factory來描述。

范例:

class TestDemo {

public static void main(String args[]) {

if(args.length != 1) {? // 沒有傳遞一個參數(shù)

System.out.println("對不起,程序執(zhí)行錯誤,正確的格式:java TestDemo 類名稱") ;

System.exit(1) ;? // 退出程序執(zhí)行

}

System.out.println("hello world !\n") ;

Computer com = new Computer() ;

com.plugin(new Flash()) ;

com.plugin(new Print()) ;

//IFruit fruit = new Apple() ;

// 利用第三方來進(jìn)行解耦合

IFruit fruit = Factory.getInstance(args[0]) ;

fruit.eat() ;

}

}

class Factory {

// 因?yàn)榇藭r(shí)Factory產(chǎn)生實(shí)例化對象沒有意義

public static IFruit getInstance(String className) {

if("apple".equals(className)) {

return new Apple() ;

}

if("orange".equals(className)) {

return new Orange() ;

}

return null ;

}

}

interface USB {

public void setup() ;? // 安裝USB驅(qū)動

public void work() ;? // 進(jìn)行工作

}

class Computer {

public void plugin(USB usb) {? //只能夠插入U(xiǎn)SB設(shè)備

usb.setup() ;

usb.work() ;

}

}

class Flash implements USB {

public void setup() {

System.out.println("安裝U盤驅(qū)動!") ;

}

public void work() {

System.out.println("進(jìn)行數(shù)據(jù)傳輸!") ;

}

}

class Print implements USB {

public void setup() {

System.out.println("安裝打印機(jī)驅(qū)動!") ;

}

public void work() {

System.out.println("進(jìn)行文件打?。?) ;

}

}

interface IFruit {

public void eat() ;

}

class Apple implements IFruit {

public void eat() {

System.out.println("\n削皮吃蘋果!") ;

}

}

class Orange implements IFruit {

public void eat() {

System.out.println("\n剝皮吃橘子!") ;

}

}

當(dāng)更換使用的IFruit子類的時(shí)候主方法沒有任何的變化就可以實(shí)現(xiàn)了子類的變更,這樣的設(shè)計(jì)就成為工廠設(shè)計(jì)模式。

總結(jié):以后只要是你編寫的接口如果要想取得接口的實(shí)例化對象,第一反應(yīng):寫工廠類。

五. 代理設(shè)計(jì)模式(Proxy)【重點(diǎn)】

所謂的代理嚴(yán)格來講就是兩個子類共同實(shí)現(xiàn)一個接口,其中一個子類負(fù)責(zé)真實(shí)的業(yè)務(wù)實(shí)現(xiàn),而另外的子類負(fù)責(zé)輔助真實(shí)業(yè)務(wù)主題的操作。


class TestDemo {

public static void main(String args[]) {

if(args == null) {

System.out.println("命令行參數(shù)為null") ;

}

if(0 == args.length) {

System.out.println("命令行參數(shù)個數(shù)為0") ;

}

if(args.length != 1) {? // 沒有傳遞一個參數(shù)

System.out.println("對不起,程序執(zhí)行錯誤,正確的格式:java TestDemo 類名稱") ;

System.exit(1) ;? // 退出程序執(zhí)行

}

System.out.println("hello world !\n") ;

Computer com = new Computer() ;

com.plugin(new Flash()) ;

com.plugin(new Print()) ;

//IFruit fruit = new Apple() ;

// 利用第三方來進(jìn)行解耦合

IFruit fruit = Factory.getInstance(args[0]) ;

fruit.eat() ;

//ISubject sub = new ProxySubject(new RealSubject()) ;

ISubject sub = Factory.getInstance() ;

// 通過代理類對象發(fā)出,利用代理類來實(shí)現(xiàn)真實(shí)業(yè)務(wù)調(diào)用

sub.save() ;

}

}

class Factory {

// 因?yàn)榇藭r(shí)Factory產(chǎn)生實(shí)例化對象沒有意義

public static IFruit getInstance(String className) {? //通過普通類去操作

if("apple".equals(className)) {

return new Apple() ;

}

if("orange".equals(className)) {? ? ? ? ? ? ? ? ? //通過代理類去操作

return new Orange() ;

}

return null ;

}

public static ISubject getInstance() {

return new ProxySubject(new RealSubject()) ;

}

}

interface USB {

public void setup() ;? // 安裝USB驅(qū)動

public void work() ;? // 進(jìn)行工作

}

class Computer {

public void plugin(USB usb) {? //只能夠插入U(xiǎn)SB設(shè)備

usb.setup() ;

usb.work() ;

}

}

class Flash implements USB {

public void setup() {

System.out.println("安裝U盤驅(qū)動!") ;

}

public void work() {

System.out.println("進(jìn)行數(shù)據(jù)傳輸!") ;

}

}

class Print implements USB {

public void setup() {

System.out.println("安裝打印機(jī)驅(qū)動!") ;

}

public void work() {

System.out.println("進(jìn)行文件打?。?) ;

}

}

interface IFruit {

public void eat() ;

}

class Apple implements IFruit {

public void eat() {

System.out.println("\n削皮吃蘋果!") ;

}

}

class Orange implements IFruit {

public void eat() {

System.out.println("\n剝皮吃橘子!") ;

}

}

interface ISubject {

public void save() ;? // 核心功能是救人

}

class RealSubject implements ISubject {

public void save() {

System.out.println("真正的制止了暴力事件!") ;

}

}

class ProxySubject implements ISubject {? // 代理實(shí)現(xiàn)

private ISubject subject ;? // 真正的操作業(yè)務(wù)

// 在創(chuàng)建代理類對象的時(shí)候必須設(shè)置要代理的真實(shí)主題

public ProxySubject(ISubject subject) {

this.subject = subject ;

}

public void broke() {

System.out.println("1、破門而入!") ;

}

public void get() {

System.out.println("2、得到見義勇為獎!") ;

}

public void save() {

this.broke() ;? ? ? ? ? // 真實(shí)操作前的準(zhǔn)備

this.subject.save() ;? ? // 調(diào)用真實(shí)的業(yè)務(wù)

this.get() ;? ? ? ? ? ? // 操作后的收尾

}

}

代理的本質(zhì):所有的真實(shí)業(yè)務(wù)操作都會有一個與之輔助的功能類共同完成。

六. 抽象類與接口的區(qū)別(面試題)

抽象類和接口都屬于常用的類結(jié)構(gòu)設(shè)計(jì),在開發(fā)之中都會出現(xiàn),不過如果按照優(yōu)先選擇來講,接口一定要比抽象類更方便。

除了單繼承的局限之外,實(shí)際上使用抽象類和接口都是類似的,但是在實(shí)際的開發(fā)之中,抽象類的設(shè)計(jì)要比接口復(fù)雜。


1. 接口是Java的核心,慢慢需要學(xué)習(xí)到接口的更多使用以及設(shè)計(jì);

2. 開發(fā)之中優(yōu)先考慮接口,以避免單繼承局限;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,706評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,568評論 19 139
  • 小編費(fèi)力收集:給你想要的面試集合 1.C++或Java中的異常處理機(jī)制的簡單原理和應(yīng)用。 當(dāng)JAVA程序違反了JA...
    八爺君閱讀 5,216評論 1 114
  • 【易經(jīng)原文·比卦初爻爻辭及象傳】 [爻辭]初六,有孚比之(1),無咎。有孚盈缶(2),終來有它(3),吉。[象傳]...
    大珊老師閱讀 1,219評論 0 3
  • 又是一年中秋夜,依舊是皓月當(dāng)空,看著天上的明月,心中不禁略過一絲寂寞。身在婆家的我,雖不是背井離鄉(xiāng),但也是...
    落英滿地閱讀 365評論 0 1

友情鏈接更多精彩內(nèi)容