Java編程之委託代理回調、內部類以及匿名內部類回調(閉包回調),委託代理回調

來源:互聯網
上載者:User

Java編程之委託代理回調、內部類以及匿名內部類回調(閉包回調),委託代理回調

最近一直在看Java的相關東西,因為我們在iOS開發是,無論是Objective-C還是Swift中,經常會用到委託代理回調,以及Block回調或者說是閉包回調。接下來我們就來看看Java語言中是如何?委託代理回調以及閉包回調的。當然這兩個技術點雖然實現起來並不困難,但是,這回調在封裝一些公用群組件時還是特別有用的。所以今天,還是有必要把Java中的委託代理回調以及閉包回調來單獨的拿出來聊一下。

本篇部落格我們依然依託於執行個體,先聊聊委託代理回調的實現和使用情境,然後再聊一下使用匿名內部類來進行回調,其實就是我們常說的“閉包”回調。閉包回調的實現方式其實就是匿名內部類的使用。既然本篇部落格我們使用到了匿名內部類,我們就再聊一下Java中的內部類的相關東西。

 

一、委託代理回調

在iOS開發中,我們經常使用到委託代理回調,想TableView、CollectionView等等,這些進階控制項會依賴於委託回調來完成一些配置。當然在Java中委託代理回調也是非常有用的,接下來我們就來看一下Java中的委託代理回調。當然在Swift或者OC中的委託代理回調是依託於“協議”的,Swift或者OC中的“協議”其實就是Java語言中的“介面”。所以在Java中的委託代理回調,依然要依託於“介面”來實現。

 

1、類圖

首先我們給出該部分執行個體的類圖,然後我們根據下方的類圖來設計實現我們的具體代碼。下方就是本部分所設計Demo的類圖,當然,從類圖中我們也能直觀的看到,該樣本是比較簡單的,一共也就是一個介面兩個類。CustomDelegate這個介面是代理類要實現的介面,其中包含了代理類要實現的方法。

從下方的類圖中我們可以看出,代理類FirstClass實現了CustomDelegate代理介面,並實現了相關的代理方法。而SecondClass依賴於CustomDelegate介面,也就是說只要是實現了CustomDelegate介面的類都可以作為SecondClass的代理。而FirstClass中含有SecondClass類型的屬性,並且FirstClass又實現了CustomDelegate介面,在FirstClass中,我們將secondClass對象的代理類指定為FirstClass,稍後我們在具體實現時將會介紹到。

  

 

2、代碼的具體實現

根據上述類圖,我們很容易的就可以給出相應的代碼實現。接下來我們就根據上述類圖來給出具體的代碼實現。

(1)、CustomDelegate的代碼實現

下方程式碼片段就是CustomDelegate的具體實現。當然該介面的實現比較簡單,就一個setValue(String value)方法。該方法的具體作用是用來相應參數回調的。下方我們會用到該方法。

package com.zeluli.callback.delegate;public interface CustomDelegate {    public void setValue(String value);}

 

(2)、SecondClass的代碼實現

CustomDelegate實現完畢後,接下來我們就來實現一下SecondClass的具體代碼。下方程式碼片段就是SecondClass的具體代碼實現了。我們從具體實現中可以明確看出,SecondClass類中有個私人的delegate屬性,該屬性是CustomDelegate類型的,所以SecondClass依賴於CustomDelegate類型。

在SecondClass的構造方法中,我們為delegate指定了具體的對象,然後調用了begin()方法。begin()方法中做的事情也是比較簡單的,就是使用了Java中內建的定時器,然後在特定時間的間隔中執行delegate對象的setValue()方法,並且將當前的時間傳給setValue()方法。

package com.zeluli.callback.delegate;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class SecondClass {    private CustomDelegate delegate;    public SecondClass(CustomDelegate delegate) {        this.delegate = delegate;        this.begin();    }        public void begin() {        TimerTask task = new TimerTask() {            @Override            public void run() {                delegate.setValue(getNowDate());    //執行委託代理回調方法            }        };                long delay = 0;          Timer timer = new Timer();          timer.scheduleAtFixedRate(task, delay, 1000);     }        private String getNowDate() {       Date currentTime = new Date();       SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");       String dateString = formatter.format(currentTime);       return dateString;    }}

 

(3)、FirstClass的建立

接下來我們來建立委託代理類,也就是我們的FirstClass類。其中的代碼也是比較簡單的,FirstClass類實現了CustomDelegate的相關方法,然後為secondClass對象指定了代理對象就是當前類的對象。具體代碼如下所示。

 1 package com.zeluli.callback.delegate; 2  3 public class FirstClass implements CustomDelegate { 4     private SecondClass secondClass; 5      6     public void beginRunSecondDelegateMethod() { 7         if(this.secondClass == null) { 8             this.secondClass = new SecondClass(this); 9         }10     }11 12     //secondClass回調要執行的方法13     @Override14     public void setValue(String value) {15         System.out.println("第二個類回調過來的值:" + value);16     }17 18 }

 

3、測試案例和運行結果

接下來我們來看一下上述代碼的測試案例和運行結果。下方程式碼片段就是我們的測試案例,代碼比較簡單,就是執行個體化了一個FirstClass的類對象firstObj,然後調用相應的方法為其中的secondClass指定代理方法即可,具體如下所示。

package com.zeluli.callback.delegate;public class Main {    public static void main(String[] args) throws InterruptedException {        FirstClass firstObj = new FirstClass();        firstObj.beginRunSecondDelegateMethod();    }}

下方就是上述代碼的運行結果,我們可以看出定期會執行FirstClass中的setValue()方法。

  

 

 

二、閉包回調

上面我們實現了委託代理回調,接下來我們來對上述樣本進行改造。將其改成匿名內部類的實現方式,也就是使用閉包的形式來實現回調。我們只需要講FirstClass進行修改即可。將其委託代理回調修改成閉包回調的形式。下方程式碼片段就是我們修改後的FirstClass類的原始碼。

從下方的原始碼可以看出,FirstClass並沒有實現CustomDelegate介面。在為SecondClass的對象指定委託代理對象時,我們傳入的是一個匿名內部類的對象,而這個對象的類型是CustomDelegate。這種用法,也是匿名內部類的使用方式之一。

  

修改後的代碼的測試案例以及運行結果與之前第一部分的委託代理回調的方式一致,在此就不做過多贅述了。

 

 

三、內部類

既然,上述我們使用到了匿名內部類,那麼接下來的這部分我們就來看看內部類的相關內容。內部類,顧名思義,就是定義在介面、類、方法等結構的內部的類。而匿名內部類,就是沒有名字的內部類,這一點也是比較好理解的。下方我們分別從迭代器的樣本以及原廠模式的樣本中來窺探一下內部類的具體使用情境及使用規則。當然這兩個樣本所針對的內部類的角度不同。

 

1、迭代器中的內部類

在之前的部落格中,我們詳細的聊了迭代器模式,詳細內容請移步於《設計模式(十):從電影院中認識"迭代器模式"(Iterator Pattern)》。當然之前的迭代器我們是使用的Swift3.0來實現的,今天部落格中我們就用Java的內部類來實現一個Java中的迭代器。

 

(1)、迭代器介面

按照之前的介紹迭代器的套路,我們還是先要建立迭代器介面的。下方的Selector就是我們建立的迭代器介面。

  • end()方法用來判斷序列是否到達了結尾處。
  • current()方法則用來擷取當前序列中下標的值。
  • next()方法則是移動下標到下一個位置。

為了統一迭代器使用規範性,所有的迭代器都要遵循該介面。具體代碼如下所示。

  

 

(2)、建立序列類以及迭代器內部類

下方建立的就是我們的序列類Sequence,該類中的items數組用來儲存元素,而next屬性指向當前值的下標。在Sequence類中,除了屬性、構造器以及方法外,我們還在其中定義了一個內部類SequenceSelector。

SequenceSelector類就是Sequence類的迭代器,並且SequenceSelector要實現迭代器介面Selector。下方我們要注意的一點,在內部類SequenceSelector中,可以直接存取外層類Sequence類的成員屬性和方法。因為無論是內部類還是Sequence類的成員屬性,都在Sequence類的域中。

當然下方的代碼的邏輯是比較簡單的,主要是對items數組的操作。具體代碼如下所示。

  

 

(3)、上述迭代器的使用

定義完迭代器後,接下來,我們就來看一下迭代器的使用呢。首先我們建立一個序列對象,然後通過for迴圈往這個序列對象裡邊添加對象。緊接著我們從這個序列對象中擷取其對應的迭代器對象,然後操作迭代器對序列進行遍曆。具體操作如下所示。

  

 

 

2、原廠模式中的匿名內部類

聊完迭代器的內部類,接下來我們來看一下原廠模式中的匿名內部類。在之前的部落格中,我們詳細的聊了原廠模式的具體內容,詳情請移步於《設計模式(四):從“兵工廠”中探索簡單工廠、Factory 方法和抽象原廠模式》。本篇部落格我們就來看一下,匿名內部類在原廠模式中的使用。

(1)、類圖

首先我們來看一下本部分所涉及案例的具體類圖,下方就是我們當前要介紹內容的類圖。

  • Service介面:首先我們來看一下Service介面,該介面是所有具體的實作類別要實現的介面。其中定義這具體的方法聲明。我們的實作類別都要繼承自該介面。
  • ServiceFactory介面:該介面是所有工廠類要實現的介面,因為本部分我們的工廠類是以匿名內部類的形式來體現的,所有該介面就是我們“匿名內部類”的類型。
  • Implemention1、2類:這兩個類就是我們的具體實作類別,我們的工廠就負責執行個體化這兩個類。
  • Factories類:該類就負責調用Factory 方法來建立相關執行個體,並執行執行個體的相關方法。

  

 

(2)、Service和ServiceFactory介面的具體實現

這兩個介面的實現代碼比較簡單,在此就不做過多贅述了,具體代碼如下所示:

 1 package com.zeluli.innerclass.factory; 2  3 public interface Service { 4     void method1(); 5     void method2(); 6 } 7  8 ====================================================== 9 10 package com.zeluli.innerclass.factory;11 12 public interface ServiceFactory {13     Service getService();14 }

 

(3)、Implementation相關類的實現

Implementation1和Implementation2的實現差不多,我們就聊一下Implementation1類的具體代碼。從下方程式碼片段中我們可以看出Implementation1類實現了Service介面,並且給出了介面中相關方法的實現。並且在Implementation1類中有一個ServiceFactory類型的靜態變數factory。而factory引用的是一個ServiceFactory類型的匿名內部類的對象。該匿名內部類就是一個工程類,其中有一個方法負責建立當前外圍類,也就是Implementation1類的對象。具體實現如下所示。

  

 

(4)、Factory類的實現

接下來我們就來看看Factory類的實現,Factory中就負責從工廠中擷取相應的對象,然後執行對象的相關方法,代碼比較簡單,就不做過多贅述了。

  

 

 

(5)、測試案例與運行結果

接下來我們來看一下上述執行個體的測試案例以及輸出結果,如下所示:

  

 

今天的部落格就先到這兒,下篇部落格會繼續聊Java的相關東西。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.