在一個應用系統中,不論使用何種編程語言,模塊之間要進行調用,僅存在三種方式:同步調用、異步調用、回調。本文就其中回調方式進行詳細解讀,並通過匿名內部類的手段,在最後實現一個同步回調的過程。
一、回調的意義
在學習回調之前,我們需要知道使用回調的原因,和回調的應用場景。
不如先思考兩個問題:
棧底對棧頂通常是不可見的,但是棧頂有時需要直接調用棧底
上級派下級做事,在此期間,下級可能需要通過上級獲取高權限的協助
而在本例中,回調方式被用來處理爬取後的大量返回數據。在業務層面,這些數據被安排在調用方進行處理,但是調用方卻沒有處理這些數據的足夠權限。於是,通過回調,業務被很好的分層並且執行。
二、如何實現同步回調
本文對同步回調的業務需求如下:
回調方調用調用方進行數據爬取
調用方調用回調方進行數據存儲
調用方調用回調方進行日誌記錄
根據需求可以得到回調過程的時序圖:
相應代碼如下:
<code>
public
interface
Handler
{void
handle
(String info)
; }public
class
Task
{private
String info;private
void
setInfo
(String info)
this
.info = info; }public
void
call
()
{ Crawler.getInstance().crawl(new
Handler() {public
void
handle
(String info)
{ setInfo(info); } }); } }public
class
Crawler
{private
static
Crawler instance =null
;public
static
CrawlergetInstance
()
{if
(instance ==null
) { instance =new
Crawler(); }return
instance; }private
StringgetInfo
()
{return
"the info from crawler"
; }public
void
crawl
(Handler handler)
{ handler.handle(getInfo()); } }/<code>三、遇到的問題
如果我們使用代碼來實現上述回調過程,不難會發現這樣一個問題:Task調用Crawler,Crawler調用Handler,Hanlder調用Task。很明顯,此處存在一個環,產生了循環依賴的問題,而接口可以為我們提供良好的解決方案。
四、為什麼通過匿名內部類的方式
用 Java 實現同步回調有許多方式,為什麼我們要通過匿名內部類的方式來實現回調,直接回調不香嗎?
不妨先看看直接回調的順序圖:
相應代碼如下:
<code>
public
interface
Handler
{void
handle
(String info)
; }public
class
Task
implements
Handler
{private
String info;private
void
setInfo
(String info)
{this
.info = info; }public
void
call
()
{ Crawler.getInstance().crawl(this
); }public
void
handle
(String info)
{ setInfo(info); } }public
class
Crawler
{private
static
Crawler instance =null
;public
static
CrawlergetInstance
()
{if
(instance ==null
) { instance =new
Crawler(); }return
instance; }private
StringgetInfo
()
{return
"the info from crawler"
; }public
void
crawl
(Handler handler)
{ handler.handle(getInfo()); } }/<code>直接回調帶來的最大問題便是回調接口的暴露,也就是說回調接口不一定用於回調,也可以用於直接訪問。這在業務層面的設計上是絕對不允許的,而匿名內部類在執行回調等特定業務的同時,可以很好的對外隱藏用於回調的接口。
五、總結
常規類通常無法對回調等特定接口作出限定,要麼都可以訪問,要麼都拒絕訪問。而內部類通過犧牲自身的被訪問權限,提升了自身訪問外部類的能力,這使得其成為實現回調的首選方案。在JAVA8中,lambda表達式本質上就是匿名內部類的語法糖。
注:匿名內部類本質上是成員內部類、局部內部類的簡化寫法,這裡將其統稱為內部類。
參考鏈接
[1] <> 卷一
[2] https://www.cnblogs.com/xrq730/p/6424471.html
[3] https://www.cnblogs.com/heshuchao/p/5376298.html
[4] https://www.cnblogs.com/dolphin0520/p/3811445.html