1. 程式人生 > >抽象類和介面的應用----常用設計模式總結

抽象類和介面的應用----常用設計模式總結

抽象類和介面是Java面向物件中最重要的概念,如果說不懂抽象類和介面,那麼對於面向物件的理解就是0分。

1,為抽象類和介面例項化

在Java中,可以通過物件的多型性為抽象類和介面例項化,這樣
在使用抽象類和介面的時候就可以呼叫子類所覆寫過的方法。

之所以抽象類和介面不能直接例項化是因為其內部包含了抽象方法,
抽象方法都是未實現的方法,無法直接呼叫。

通過物件多型性可以發現,子類發生了向上轉型之後,所呼叫的全部方法
都是被覆寫過的方法。

abstract class A{   // 定義抽象類A
    public abstract void print() ;  // 定義抽象方法print()
}; class B extends A { // 定義子類,繼承抽象類 public void print(){ // 覆寫抽象方法 System.out.println("Hello World!!!") ; } }; public class AbstractCaseDemo01{ public static void main(String args[]){ A a = new B() ; // 通過子類為抽象類例項化 a.print() ; } };

這裡寫圖片描述

interface A{    // 定義介面A
void print() ; // 定義抽象方法print() }; class B implements A { // 定義子類,實現介面 public void print(){ // 覆寫抽象方法 System.out.println("Hello World!!!") ; } }; public class InterfaceCaseDemo01{ public static void main(String args[]){ A a = new B() ; // 通過子類為抽象類例項化 a.print
() ; } };

這裡寫圖片描述

要使用抽象類和介面就得按照這樣的使用方式進行(通過子類進行使用),否則是無法進行使用的。

2,抽象類的應用—-定義模板

2-1:場景1,

這裡寫圖片描述

abstract class Person{
    private String name ;       // 定義name屬性
    private int age ;           // 定義age屬性
    public Person(String name,int age){
        this.name = name ;
        this.age = age ;
    }
    public String getName(){
        return this.name ;
    }
    public int getAge(){
        return this.age ;
    }
    public void say(){      // 人說話是一個具體的功能
        System.out.println(this.getContent()) ; // 輸出內容
    }
    public abstract String getContent() ;   // 說話的內容由子類決定
};
class Student extends Person{
    private float score ;
    public Student(String name,int age,float score){
        super(name,age) ;   // 呼叫父類中的構造方法
        this.score = score ;
    }
    public String getContent(){
        return  "學生資訊 --> 姓名:" + super.getName() + 
                ";年齡:" + super.getAge() + 
                ";成績:" + this.score ;
    }
};
class Worker extends Person{
    private float salary ;
    public Worker(String name,int age,float salary){
        super(name,age) ;   // 呼叫父類中的構造方法
        this.salary = salary ;
    }
    public String getContent(){
        return  "工人資訊 --> 姓名:" + super.getName() + 
                ";年齡:" + super.getAge() + 
                ";工資:" + this.salary ;
    }
};
public class AbstractCaseDemo02{
    public static void main(String args[]){
        Person per1 = null ;    // 宣告Person物件
        Person per2 = null ;    // 宣告Person物件
        per1 = new Student("張三",20,99.0f) ; // 學生是一個人
        per2 = new Worker("李四",30,3000.0f) ;    // 工人是一個人
        per1.say() ;    // 學生說學生的話
        per2.say() ;    // 工人說工人的話
    }
};

**分析:

1,說話這個功能,正常的是個人都有這個功能,所以可以抽取出來,在Person這個類中,定義一個say()方法,但是說話的內容,不同的型別的人討論的話題不同,這個話題,不能寫成具體的,需要定義成一個抽象的方法,在不同的子類中實現不同的內容。

2,一個人,無論是工人還是學生或者其他什麼人,想說話麼,想說話,就覆寫我的getContent()方法,就是這樣規定好了,這就是模板,

2-2:場景2,

這裡寫圖片描述

3,介面的應用—-

3-1,制定標準。

3-2,將方法的檢視暴露給遠端的客戶端(分散式應用中)。

場景

這裡寫圖片描述

interface USB{      // 定義了USB介面,制定標準
    public void start() ;   // USB裝置開始工作
    public void stop() ;    // USB裝置結束工作
}
class Computer{
    public static void plugin(USB usb){ // 電腦上可以插入USB裝置,只要符合usb介面就可以插入
        usb.start() ;
        System.out.println("=========== USB 裝置工作 ========") ;
        usb.stop() ;
    }
};
class Flash implements USB{
    public void start(){    // 覆寫方法
        System.out.println("U盤開始工作。") ;
    }
    public void stop(){     // 覆寫方法
        System.out.println("U盤停止工作。") ;
    }
};
class Print implements USB{
    public void start(){    // 覆寫方法
        System.out.println("印表機開始工作。") ;
    }
    public void stop(){     // 覆寫方法
        System.out.println("印表機停止工作。") ;
    }
};
public class InterfaceCaseDemo02{
    public static void main(String args[]){
        Computer.plugin(new Flash()) ;
        Computer.plugin(new Print()) ;
    }
};

這裡寫圖片描述

4,工廠設計模式(介面的應用)

是Java中最長使用的一種設計模式,工廠有什麼用呢?

interface Fruit{    // 定義一個水果介面
    public void eat() ; // 吃水果
}
class Apple implements Fruit{
    public void eat(){
        System.out.println("** 吃蘋果。") ;
    }
};
class Orange implements Fruit{
    public void eat(){
        System.out.println("** 吃橘子。") ;
    }
};
public class InterfaceCaseDemo03{
    public static void main(String args[]){
        Fruit f = new Apple() ; // 例項化介面
        f.eat() ;
    }
};

主方法相當於一個客戶端,主方法的程式碼越說越好。此時,直接在主方法中
指定了要操作的子類,如果要修改子類,肯定要修改客戶端。就是說,現在
系統和特定的子類緊密的耦合在一起了,必須要進行解耦和,否則在擴充套件的
時候,會遇到想象不到的困難。

分析

這裡寫圖片描述

客戶端通過一個過渡段,找到特定的子類,客戶端尋找特定子類的操作以

介面為標準。這個過渡段,在程式中就稱為工廠設計。

interface Fruit{    // 定義一個水果介面
    public void eat() ; // 吃水果
}
class Apple implements Fruit{
    public void eat(){
        System.out.println("** 吃蘋果。") ;
    }
};
class Orange implements Fruit{
    public void eat(){
        System.out.println("** 吃橘子。") ;
    }
};
class Factory{  // 定義工廠類
    public static Fruit getInstance(String className){
        Fruit f = null ;
        if("apple".equals(className)){  // 判斷是否要的是蘋果的子類
            f = new Apple() ;
        }
        if("orange".equals(className)){ // 判斷是否要的是橘子的子類
            f = new Orange() ;
        }
        return f ;
    }
};

public class InterfaceCaseDemo04{
    public static void main(String args[]){
        Fruit f = Factory.getInstance("apple") ;    // 例項化介面
        f.eat() ;
    }
};

客戶端通過工廠類取得子類物件,工廠類裡面通過判斷,例項化對應的子類物件,
返回給工廠,然後向上轉型之後再,返回介面物件給客戶端,之後,客戶端通過
介面物件呼叫介面中的方法,這樣就完成了程式碼的整個操作過程。
這裡寫圖片描述

這是簡單的工廠的使用,但是這裡還是存在缺陷,比如,首先,傳入的字串不是”apple”,又不是”orange”,此時返回的Fruit物件是null,就出現問題了,其次,這種字串的比較方式,在客戶端將這個字串固定死了,程式缺乏靈活性了,

這兩個缺陷,也是有解決辦法的,這裡先不贅述了,參考我的這一片部落格,工廠模式

5,代理設計模式(介面的應用)

1場景

這裡寫圖片描述

場景2

這裡寫圖片描述

分析

這裡寫圖片描述

interface Network{
    public void browse() ;  // 瀏覽
}
class Real implements Network{
    public void browse(){
        System.out.println("上網瀏覽資訊") ;
    }
};
class Proxy implements Network{
    private Network network ;   // 代理物件
    public Proxy(Network network){
        this.network = network ;
    }
    public void check(){
        System.out.println("檢查使用者是否合法。") ;
    }
    public void browse(){
        this.check() ;
        this.network.browse() ; // 呼叫真實的主題操作
    }
};
public class ProxyDemo{
    public static void main(String args[]){
        Network net = null ;
        net  = new Proxy(new Real()) ;//  指定代理操作
        net.browse() ;  // 客戶只關心上網瀏覽一個操作
    }
};

這裡寫圖片描述

分析

首先定義一個標準(介面)Network,功能就是瀏覽;然後,Real是真正的上網伺服器,
功能是上網,她實現NetWork介面,並實現介面中的瀏覽方法,實現真正的瀏覽功能;然後,
Proxy是代理伺服器,功能也是上網,實現Network介面,首先給出代理物件,在實現上網功能之前,完成了其他功能,
比如,進行使用者是否合法的判斷,然後再實現的network的介面中,執行代理伺服器的所有功能。
代理伺服器,除了代理其主要功能外,還做了一些與其主要功能相關的功能,這就是代理,完成的更多的功能,(主要功能是從委託類中代理來的
,相關功能在代理類中自己定義的這些相關的功能,被代理類中是不想做這些工作的,所以放在代理類中進行)
這裡寫圖片描述

6,介面卡設計模式(介面和抽象類的應用)

該模式在圖形Java介面的程式設計上使用的比較多,在Android的開發中使用的是最多的。

場景:

這裡寫圖片描述

這裡寫圖片描述

interface Window{       // 定義Window介面,表示視窗操作
    public void open() ;    // 開啟
    public void close() ;   // 關閉
    public void activated() ;   // 視窗活動
    public void iconified() ;   // 視窗最小化
    public void deiconified();// 視窗恢復大小
}
abstract class WindowAdapter implements Window{
    public void open(){} ;  // 開啟
    public void close(){} ; // 關閉
    public void activated(){} ; // 視窗活動
    public void iconified(){} ; // 視窗最小化
    public void deiconified(){};// 視窗恢復大小
};
class WindowImpl extends WindowAdapter{
    public void open(){
        System.out.println("視窗開啟。") ;
    }
    public void close(){
        System.out.println("視窗關閉。") ;
    }
};
public class AdapterDemo{
    public static void main(String args[]){
        Window win = new WindowImpl() ;
        win.open() ;
        win.close() ;
    }
};

這裡寫圖片描述

7,內部類擴充套件

抽象類中可以包含若干個介面。介面中也可以定義若干抽象類。

7-1,抽象類內部包含介面

不實現內部介面

abstract class A{   // 定義抽象類
    public abstract void printA() ; // 抽象方法
    interface B{    // 定義內部介面
        public void printB() ;  // 定義抽象方法
    }
};
class X extends A{  // 繼承抽象類
    public void printA(){
        System.out.println("HELLO --> A") ;
    }
};
public class InnerExtDemo01{
    public static void main(String args[]){
        A x=new X();
        x.printA();
    }
};

這裡寫圖片描述

實現內部介面

abstract class A{   // 定義抽象類
    public abstract void printA() ; // 抽象方法
    interface B{    // 定義內部介面
        public void printB() ;  // 定義抽象方法
    }
};
class X extends A{  // 繼承抽象類
    public void printA(){
        System.out.println("HELLO --> A") ;
    }
    class Y implements B{   // 定義內部類實現內部介面
        public void printB(){
            System.out.println("HELLO --> B") ;
        }
    };
};
public class InnerExtDemo01{
    public static void main(String args[]){
        A.B b = new X().new Y() ;
        b.printB() ;
    }
};

這裡寫圖片描述

7-2,介面中包含內部抽象類

不繼內部承抽象類

interface A{    // 定義介面
    public void printA() ;  // 抽象方法
    abstract class B{   // 定義內部抽象類
        public abstract void printB() ; // 定義抽象方法
    }
};
class X implements A{   // 實現介面
    public void printA(){
        System.out.println("HELLO --> A") ;
    }
};
public class InnerExtDemo02{
    public static void main(String args[]){
        A a=new X();
        a.printA();
    }
};

繼承內部抽象類

interface A{    // 定義介面
    public void printA() ;  // 抽象方法
    abstract class B{   // 定義內部抽象類
        public abstract void printB() ; // 定義抽象方法
    }
};
class X implements A{   // 實現介面
    public void printA(){
        System.out.println("HELLO --> A") ;
    }
    class Y extends B{  // 繼承抽象類
        public void printB(){
            System.out.println("HELLO --> B") ;
        }
    };
};
public class InnerExtDemo02{
    public static void main(String args[]){
        A.B b = new X().new Y() ;
        b.printB() ;
    }
};

這裡寫圖片描述

8,介面與抽象類的關係

這裡寫圖片描述

這裡寫圖片描述

總結:

在開發中,一個類永遠不要去繼承一個已經實現好的類,要麼繼承抽象類,要麼實現介面,如果抽象類和介面可以同時使用的話,優先使用介面,可以避免單繼承的侷限。