10.JAVA-接口、工廠模式、代理模式、詳解


1.接口定義

接口屬於一個特殊的類,這個類里面只能有抽象方法全局常量  (該概念在JDK1.8之后被打破,在1.8后接口中還可以定義普通方法靜態方法,在后續章節會詳講)

1.1 接口具有以下幾個原則

  • 接口通過interface關鍵字來實現定義
  • 一個子類如果要繼承接口的話,則需要通過implements關鍵字去實現多個接口(多接口之間通過","隔開),從而實現多繼承.
  • 接口的子類如果不是個抽象類,則必須要覆寫接口的所有抽象方法,才能承認該類實現了這個接口
  • 接口的子對象可以通過向上轉型進行實例化操作

1.2 接下來來個示例,通過Demo類繼承InA和InB兩個接口

interface InA                     //接口InA
{
         public static final String ATTR = "Attribute:InA";
         public abstract void PrintA();
}

interface InB                     //接口InB
{
         public static final String ATTR = "Attribute:InB";
         public abstract void PrintB();
}

class Demo  implements InA,InB 
{
         public void PrintA()
         {
                  System.out.println(InA.ATTR);        //打印接口A的全局常量
         }
         public void PrintB()
         {
                  System.out.println(InB.ATTR);        //打印接口B的全局常量
         }
}

public class Test{
         public static void print(InB b)                  //接口支持向上轉型
         {
                  b.PrintB();
         }
         public static void main(String args[])
         {
                  Demo d = new Demo();
                  d.PrintA();                    //打印接口A的全局常量
                  print(d);                       //等價於d.PrintB();
         }
}

運行打印:

 

從上面代碼可以看出,接口實際上只是表示一種操作標准  ,而接口本身其實是沒有操作能力的,需要子類去實現這個操作能力才行.

 

2.接口的簡化定義

由於接口組成部分是抽象方法全局常量,所以在方法和常量上寫不寫public結果都一樣,並且方法也可以不用abstract修飾,因為接口里的訪問權限都是public的,並且方法默認為抽象的,所以InA接口也可以寫為下面這樣:

interface InA                     //接口InA
{
         String ATTR = "Attribute:InA";     //不需要添加public static final void PrintA();             //不需要添加public abstract
}

 

3.接口定義注意的地方

3.1 對於子類或者抽象子類,可以同時繼承抽象類以及多個接口,比如:

class Demo extends A  implements InA,InB{     // Demo子類繼承於A類,以及接口inA和inB
         //... ...    //實現所有抽象方法
}

3.2 對於一個子接口,可以通過extends來繼承多個父接口,比如:

interface InC extends InA,InB{                 //InC子接口繼承父接口inA和inB
         public void funcC();   //定義抽象方法
}

3.3 接口不能繼承於抽象類,因為extends關鍵字用於繼承同一品種的(接口!=抽象類),而 implements用於繼承於接口的(抽象類!=接口),所以無法實現.

 

4.接口之工廠設計模式Factory

工廠設計模式,就是說建立一個工廠類,對實現了同一接口的子類們進行統一的實例創建方法,用來提供給用戶調用.而用戶無需去了解這些對象該如何創建以及如何組織.

4.1工廠設計示例

我們以常用的usb為例,首先需要定義一個USB接口,然后寫同一接口的子類們(比如:鍵盤,鼠標,打印機).由於這些子類們都是獨立的,所以我們需要在定義一個工廠類UsbFactory,通過一個方法去統一創建他們,如果不寫工廠類的話,假如有100多個USB子類,那豈不是全部創建都要100多個不同的new才行?所以需要一個工廠類負責管理這些對象.

首先定義USB接口和鍵盤,鼠標子類:

interface USB           //USB接口
{
         public void plugin();
         public void out();
}
class Keyboard  implements USB
{
         public void plugin()
         {
                  System.out.println("****插上 usb鍵盤****");
         }
         public void out()
         {
                  System.out.println("****取出 usb鍵盤****");
         }
}

class Mouse  implements USB
{
         public void plugin()
         {
                  System.out.println("****插上 usb鼠標****");
         }

         public void out()
         {
                  System.out.println("****取出 usb鼠標****");
         }
}

然后定義UsbFactory工廠類:

class UsbFactory
{
         static public USB getInstance(String name)
         {
                  if("keyboard".equals(name))  //是否為鍵盤
                          return new Keyboard();
                  else if("mouse".equals(name))        //是否為鍵盤
                          return new Mouse();
                  else
                          return null;
         }
}

最后寫測試代碼:

public class Test{
         public static void main(String args[])
         {
                          USB usb1 = UsbFactory.getInstance("keyboard");   //獲取鍵盤類
                          usb1.plugin();
                          usb1.out();

                          USB usb2 = UsbFactory.getInstance("mouse");    //獲取鼠標類
                          usb2.plugin();
         }
}

打印如下:

 

從上面代碼可以看出,通過工廠模式,我們可以更加容易地管理多個相同接口的子類們的操作.

PS:當前工廠模式還是最簡單的,在后續學到反射機制泛型后,在講解. 

 

5.代理模式proxy

代理模式,就是說為一個具體對象提供一個代理對象,該代理對象主要是為了封裝具體對象,並且完成與具體對象有關的所有操作.而具體對象只需要負責核心業務.

5.1 代理設計示例

我們以生活中的Eat吃為例,首先需要定義一個Eat接口,然后寫一個具體類WhatEat(用來指定具體吃什么),但是在生活中,我們如果吃的不是水果,而是蔬菜,則都要有盤子啊,並且吃之前要先去燒菜盛菜,並且吃完后還要洗碗.而這些操作,我們就不能寫在WhatEat類里,因為WhatEat類只負責核心業務(吃),所以便有了代理對象(完成與具體對象有關的所有操作),接下來便寫一個EatProxy代理節點類來實現這些與WhatEat類操作.

首先定義Eat接口和具體吃的類(WhatEat):

interface Eat
{
         public int TypeVegetable = 0;      //蔬菜
         public int TypeFruit = 1;          //水果
         public void eat(int type);
}

class WhatEat implements Eat
{
         public void eat(int type)
         {
                  if(type == Eat.TypeVegetable)
                          System.out.println("*** 吃蔬菜 ***");
                  else
                          System.out.println("*** 吃水果 ***");
         }
}

然后定義EatProxy代理節點類:

class EatProxy implements Eat
{
         private Eat eatObject;     //代理下的具體對象

         public EatProxy(Eat eatObject)
         {
                  this.eatObject = eatObject;
         }

         public void eat(int type)                  //吃東西
         {
                  this.eatPrepare(type);
                  this.eatObject.eat(type);
                  this.eatFinish(type);
         }
 
         private void eatPrepare(int type) //吃東西之前的准備工作
         {
                  if(type == Eat.TypeVegetable)
                  {
                          System.out.println("正在燒菜... ...");
                          System.out.println("燒菜完成,正在盛菜");
                          System.out.println("盛菜完成,准備開吃");
                  }
                  else
                  {
                          System.out.println("正在洗水果,削皮中...");
                          System.out.println("削皮完成,准備開吃");
                  }
         }

         private void eatFinish(int type) //吃完東西之后的工作
         {
                  if(type == Eat.TypeVegetable)
                  {
                          System.out.println("吃完了,准備洗碗...");
                  }
                  else
                  {
                          System.out.println("吃完了,准備干其它事...");
                  }
         }
}

最后寫測試代碼:

public class Test{
         public static void main(String args[])
         {
                  EatProxy  proxy = new EatProxy(new WhatEat());

                  proxy.eat(Eat.TypeFruit);                 //通過代理節點吃水果

                  //分割線
                  System.out.println();
                  System.out.println();

                  proxy.eat(Eat.TypeVegetable);             //通過代理節點吃蔬菜
         }
}

打印如下所示:

 

從上面可以看到,我們WhatEat類只需要完成吃(核心業務),可以發現通過代理可以降低不同類之間的依賴性

 6.總結

學完接口后,它和抽象類之間的區別如下

區別

抽象類

接口

關鍵字

abstract class

interface

內部組成

支持屬性,常量,構造方法,普通方法,abstract抽象方法,靜態方法等

支持全局常量,abstract抽象方法

子類繼承

class 子類 extends 抽象類{

//... ...

}

class 子類 interface 接口1,接口2,...{

//... ...

}

自身繼承

抽象類可以繼承於多個接口,或者抽象類.

接口可以繼承多個接口,但不能繼承抽象類.

繼承限制

單繼承,一個子類只能繼承一個抽象類

多繼承,一個子類可以繼承多個接口

 

下章學習:11.JAVA-Object類之finalize(),clone(),toString()等方法覆寫

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM