詳談Java編程之委托代理回調、內部類以及匿名內部類回調(閉包回調)
最近一直在看Java的相關東西,因為我們在iOS開發(fā)是,無論是Objective-C還是Swift中,經(jīng)常會用到委托代理回調,以及Block回調或者說是閉包回調。接下來我們就來看看Java語言中是如何實現(xiàn)委托代理回調以及閉包回調的。當然這兩個技術點雖然實現(xiàn)起來并不困難,但是,這回調在封裝一些公用組件時還是特別有用的。所以今天,還是有必要把Java中的委托代理回調以及閉包回調來單獨的拿出來聊一下。
本篇博客我們依然依托于實例,先聊聊委托代理回調的實現(xiàn)和使用場景,然后再聊一下使用匿名內部類來進行回調,其實就是我們常說的“閉包”回調。閉包回調的實現(xiàn)方式其實就是匿名內部類的使用。既然本篇博客我們使用到了匿名內部類,我們就再聊一下Java中的內部類的相關東西。
一、委托代理回調
在iOS開發(fā)中,我們經(jīng)常使用到委托代理回調,想TableView、CollectionView等等,這些高級控件會依賴于委托回調來完成一些配置。當然在Java中委托代理回調也是非常有用的,接下來我們就來看一下Java中的委托代理回調。當然在Swift或者OC中的委托代理回調是依托于“協(xié)議”的,Swift或者OC中的“協(xié)議”其實就是Java語言中的“接口”。所以在Java中的委托代理回調,依然要依托于“接口”來實現(xiàn)。
1、類圖
首先我們給出該部分實例的類圖,然后我們根據(jù)下方的類圖來設計實現(xiàn)我們的具體代碼。下方就是本部分所設計Demo的類圖,當然,從類圖中我們也能直觀的看到,該示例是比較簡單的,一共也就是一個接口兩個類。CustomDelegate這個接口是代理類要實現(xiàn)的接口,其中包含了代理類要實現(xiàn)的方法。
從下方的類圖中我們可以看出,代理類FirstClass實現(xiàn)了CustomDelegate代理接口,并實現(xiàn)了相關的代理方法。而SecondClass依賴于CustomDelegate接口,也就是說只要是實現(xiàn)了CustomDelegate接口的類都可以作為SecondClass的代理。而FirstClass中含有SecondClass類型的屬性,并且FirstClass又實現(xiàn)了CustomDelegate接口,在FirstClass中,我們將secondClass對象的代理類指定為FirstClass,稍后我們在具體實現(xiàn)時將會介紹到。

2、代碼的具體實現(xiàn)
根據(jù)上述類圖,我們很容易的就可以給出相應的代碼實現(xiàn)。接下來我們就根據(jù)上述類圖來給出具體的代碼實現(xiàn)。
(1)、CustomDelegate的代碼實現(xiàn)
下方代碼段就是CustomDelegate的具體實現(xiàn)。當然該接口的實現(xiàn)比較簡單,就一個setValue(String value)方法。該方法的具體作用是用來相應參數(shù)回調的。下方我們會用到該方法。
package com.zeluli.callback.delegate;
public interface CustomDelegate {
public void setValue(String value);
}
(2)、SecondClass的代碼實現(xiàn)
CustomDelegate實現(xiàn)完畢后,接下來我們就來實現(xiàn)一下SecondClass的具體代碼。下方代碼段就是SecondClass的具體代碼實現(xiàn)了。我們從具體實現(xiàn)中可以明確看出,SecondClass類中有個私有的delegate屬性,該屬性是CustomDelegate類型的,所以SecondClass依賴于CustomDelegate類型。
在SecondClass的構造方法中,我們?yōu)閐elegate指定了具體的對象,然后調用了begin()方法。begin()方法中做的事情也是比較簡單的,就是使用了Java中自帶的定時器,然后在特定時間的間隔中執(zhí)行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()); //執(zhí)行委托代理回調方法
}
};
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的創(chuàng)建
接下來我們來創(chuàng)建委托代理類,也就是我們的FirstClass類。其中的代碼也是比較簡單的,F(xiàn)irstClass類實現(xiàn)了CustomDelegate的相關方法,然后為secondClass對象指定了代理對象就是當前類的對象。具體代碼如下所示。
package com.zeluli.callback.delegate;
public class FirstClass implements CustomDelegate {
private SecondClass secondClass;
public void beginRunSecondDelegateMethod() {
if(this.secondClass == null) {
this.secondClass = new SecondClass(this);
}
}
//secondClass回調要執(zhí)行的方法
@Override
public void setValue(String value) {
System.out.println("第二個類回調過來的值:" + value);
}
}
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();
}
}
下方就是上述代碼的運行結果,我們可以看出定期會執(zhí)行FirstClass中的setValue()方法。

二、閉包回調
上面我們實現(xiàn)了委托代理回調,接下來我們來對上述示例進行改造。將其改成匿名內部類的實現(xiàn)方式,也就是使用閉包的形式來實現(xiàn)回調。我們只需要講FirstClass進行修改即可。將其委托代理回調修改成閉包回調的形式。下方代碼段就是我們修改后的FirstClass類的源代碼。
從下方的源代碼可以看出,F(xiàn)irstClass并沒有實現(xiàn)CustomDelegate接口。在為SecondClass的對象指定委托代理對象時,我們傳入的是一個匿名內部類的對象,而這個對象的類型是CustomDelegate。這種用法,也是匿名內部類的使用方式之一。

修改后的代碼的測試用例以及運行結果與之前第一部分的委托代理回調的方式一致,在此就不做過多贅述了。
三、內部類
既然,上述我們使用到了匿名內部類,那么接下來的這部分我們就來看看內部類的相關內容。內部類,顧名思義,就是定義在接口、類、方法等結構的內部的類。而匿名內部類,就是沒有名字的內部類,這一點也是比較好理解的。下方我們分別從迭代器的示例以及工廠模式的示例中來窺探一下內部類的具體使用場景及使用規(guī)則。當然這兩個示例所針對的內部類的角度不同。
1、迭代器中的內部類
在之前的文章中,我們詳細的聊了迭代器模式,當然之前的迭代器我們是使用的Swift3.0來實現(xiàn)的,今天我們就用Java的內部類來實現(xiàn)一個Java中的迭代器。
(1)、迭代器接口
按照之前的介紹迭代器的套路,我們還是先要創(chuàng)建迭代器接口的。下方的Selector就是我們創(chuàng)建的迭代器接口。
end()方法用來判斷序列是否到達了結尾處。
current()方法則用來獲取當前序列中下標的值。
next()方法則是移動下標到下一個位置。
為了統(tǒng)一迭代器使用規(guī)范性,所有的迭代器都要遵循該接口。具體代碼如下所示。

(2)、創(chuàng)建序列類以及迭代器內部類
下方創(chuàng)建的就是我們的序列類Sequence,該類中的items數(shù)組用來存儲元素,而next屬性指向當前值的下標。在Sequence類中,除了屬性、構造器以及方法外,我們還在其中定義了一個內部類SequenceSelector。
SequenceSelector類就是Sequence類的迭代器,并且SequenceSelector要實現(xiàn)迭代器接口Selector。下方我們要注意的一點,在內部類SequenceSelector中,可以直接訪問外層類Sequence類的成員屬性和方法。因為無論是內部類還是Sequence類的成員屬性,都在Sequence類的域中。
當然下方的代碼的邏輯是比較簡單的,主要是對items數(shù)組的操作。具體代碼如下所示。

(3)、上述迭代器的使用
定義完迭代器后,接下來,我們就來看一下迭代器的使用呢。首先我們創(chuàng)建一個序列對象,然后通過for循環(huán)往這個序列對象里邊添加對象。緊接著我們從這個序列對象中獲取其對應的迭代器對象,然后操作迭代器對序列進行遍歷。具體操作如下所示。

2、工廠模式中的匿名內部類
聊完迭代器的內部類,接下來我們來看一下工廠模式中的匿名內部類。在之前的文章中,我們詳細的聊了工廠模式的具體內容。本篇文章我們就來看一下,匿名內部類在工廠模式中的使用。
(1)、類圖
Service接口:首先我們來看一下Service接口,該接口是所有具體的實現(xiàn)類要實現(xiàn)的接口。其中定義這具體的方法聲明。我們的實現(xiàn)類都要繼承自該接口。
ServiceFactory接口:該接口是所有工廠類要實現(xiàn)的接口,因為本部分我們的工廠類是以匿名內部類的形式來體現(xiàn)的,所有該接口就是我們“匿名內部類”的類型。
Implemention1、2類:這兩個類就是我們的具體實現(xiàn)類,我們的工廠就負責實例化這兩個類。
Factories類:該類就負責調用工廠方法來創(chuàng)建相關實例,并執(zhí)行實例的相關方法。

(2)、Service和ServiceFactory接口的具體實現(xiàn)
這兩個接口的實現(xiàn)代碼比較簡單,在此就不做過多贅述了,具體代碼如下所示:
package com.zeluli.innerclass.factory;
public interface Service {
void method1();
void method2();
}
======================================================
package com.zeluli.innerclass.factory;
public interface ServiceFactory {
Service getService();
}
(3)、Implementation相關類的實現(xiàn)
Implementation1和Implementation2的實現(xiàn)差不多,我們就聊一下Implementation1類的具體代碼。從下方代碼片段中我們可以看出Implementation1類實現(xiàn)了Service接口,并且給出了接口中相關方法的實現(xiàn)。并且在Implementation1類中有一個ServiceFactory類型的靜態(tài)變量factory。而factory引用的是一個ServiceFactory類型的匿名內部類的對象。該匿名內部類就是一個工程類,其中有一個方法負責創(chuàng)建當前外圍類,也就是Implementation1類的對象。具體實現(xiàn)如下所示。

(4)、Factory類的實現(xiàn)
接下來我們就來看看Factory類的實現(xiàn),F(xiàn)actory中就負責從工廠中獲取相應的對象,然后執(zhí)行對象的相關方法,代碼比較簡單,就不做過多贅述了。

(5)、測試用例與運行結果
接下來我們來看一下上述實例的測試用例以及輸出結果,如下所示:

以上這篇詳談Java編程之委托代理回調、內部類以及匿名內部類回調(閉包回調)就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Javaweb實現(xiàn)在線人數(shù)統(tǒng)計代碼實例
這篇文章主要介紹了Javaweb實現(xiàn)在線人數(shù)統(tǒng)計代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-11-11
IDEA搭建SpringBoot多模塊聚合工程過程詳解(多模塊聚合工程)
這篇文章主要是介紹一下,如何在IDEA開發(fā)工具下,搭建一個基于SpringBoot的多模塊聚合工程項目,本篇文章,將項目模塊細分為幾個子工程模塊,在文中給大家詳細介紹過,對IDEA搭建SpringBoot多模塊聚合工程感興趣的朋友一起看看吧2022-04-04
java 遞歸查詢所有子節(jié)點id的方法實現(xiàn)
在多層次的數(shù)據(jù)結構中,經(jīng)常需要查詢一個節(jié)點下的所有子節(jié)點,本文主要介紹了java 遞歸查詢所有子節(jié)點id的方法實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-03-03
Spring Boot集成starrocks快速入門Demo(適用場景)
StarRocks 是新一代極速全場景 MPP (Massively Parallel Processing) 數(shù)據(jù)庫,StarRocks 的愿景是能夠讓用戶的數(shù)據(jù)分析變得更加簡單和敏捷,這篇文章主要介紹了Spring Boot集成starrocks快速入門Demo,需要的朋友可以參考下2024-08-08
Java Idea TranslationPlugin翻譯插件使用解析
這篇文章主要介紹了Java Idea TranslationPlugin翻譯插件使用解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-04-04
Mybatis如何按順序查詢出對應的數(shù)據(jù)字段
這篇文章主要介紹了Mybatis如何按順序查詢出對應的數(shù)據(jù)字段,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01
SpringBoot使用MockMvc測試get和post接口的示例代碼
Spring Boot MockMvc是一個用于單元測試的模塊,它是Spring框架的一部分,專注于簡化Web應用程序的測試,MockMvc主要用來模擬一個完整的HTTP請求-響應生命周期,本文給大家介紹了SpringBoot使用MockMvc測試get和post接口,需要的朋友可以參考下2024-06-06

