在咱們設計和開發應用程序時,常常要用到控件。好比開發一個客戶端WinForm應用程序時,微軟就爲咱們提供了若干控件,這些控件爲咱們提供了可被定製的屬性和事件。屬性能夠更改它的外觀,好比背景色,標題等,而事件能夠豐富控件的行爲,好比最多見的『按鈕點擊』,誰也不能肯定點擊以後將發生什麼事,是鏈接數據庫呢仍是彈出警告框,在不一樣的場景下,『按鈕點擊』 的行爲每每呈現不一致。因此,與其猶豫不定,還不如把處理委託給開發者,這就是『OnClick』事件。git
在上篇文章中,我闡述了爲何要使用SubView,總結起來就3個字:『可複用』 。那麼問題來了,既然是可複用,那就意味着SubView能夠在任何場景下使用,那怎樣才能確保它作的是正確的行爲呢?github
舉個栗子,仍是 以以下圖FaceBox爲例,不一樣的場景下點擊頭像應該處理不一樣的事:數據庫
你看,一樣一個SubView,在不一樣的場景下它的行爲每每是不一致的。那咱們怎麼去跟蹤這些行爲呢?設計模式
你可能會以以下方式去定製SubView的行爲:ide
void OnClick(){
if(戰團){
顯示該成員的具體信息
}else if(隊伍){
進入換人界面
}else if(戰鬥){
顯示它配置的戰術
}else{
//其餘
}
}複製代碼
仍是那句話這樣,這樣並無錯,甚至對某些SubView而言邏輯還很清晰。但仔細想一想,這是最好的實踐嗎?spa
因此顯然上述代碼不是最佳實踐。那咱們應該怎樣去解決呢?設計
實際從開頭的引言我已經提出瞭解決方案,以事件的形式委託給開發者來肯定。一個Button也好,仍是一個SubView也好,他們都是可複用的組件,不該該與具體的業務邏輯相結合。經過事件或者委託的形式,暴露給開發者來決定究竟要處理什麼邏輯,這樣才能和具體業務邏輯解耦。代理
仍是以FaceBox舉例,那麼從上面的分析得出結論,咱們須要定義委託或者事件,那應該定義在FaceBoxView呢仍是FaceBoxViewModel中呢?code
仍是那句話,View不處理具體的業務邏輯,View將請求交給ViewModel去處理。orm
故在FaceBoxViewModel中增長可被外界監聽的委託或者事件,我以委託舉例,實際上事件就是特殊的委託。
public class FaceBoxViewModel:ViewModelBase
{
//省略部分代碼
public delegate void OnBeginDragHandler();
public OnBeginDragHandler OnBeginDrag;
public delegate void OnDragHandler();
public OnDragHandler OnDrag;
public delegate void OnEndDragHandler();
public OnEndDragHandler OnEndDrag;
public delegate void OnClickHandler();
public OnClickHandler OnClick;
//省略部分代碼
}複製代碼
FaceBoxView不處理具體的邏輯,交由FaceBoxViewModel去實現:
protected override void OnInitialize() {
//省略部分代碼
//監聽事件
var beginDragEntry = new EventTrigger.Entry();
beginDragEntry.eventID = EventTriggerType.BeginDrag;
beginDragEntry.callback.AddListener(eventData => { OnBeginDrag(); });
eventTrigger.triggers.Add(beginDragEntry);
var dragEntry = new EventTrigger.Entry();
dragEntry.eventID = EventTriggerType.Drag;
dragEntry.callback.AddListener(eventData => { OnDrag(); });
eventTrigger.triggers.Add(dragEntry);
var endDragEntry = new EventTrigger.Entry();
endDragEntry.eventID = EventTriggerType.EndDrag;
endDragEntry.callback.AddListener(eventData => { OnEndDrag(); });
eventTrigger.triggers.Add(endDragEntry);
var pointClickEntry = new EventTrigger.Entry();
pointClickEntry.eventID = EventTriggerType.PointerClick;
pointClickEntry.callback.AddListener(eventData => { OnClick(); });
eventTrigger.triggers.Add(pointClickEntry);
}
private void OnClick() {
if (BindingContext.OnClick != null)
{
BindingContext.OnClick();
}
}複製代碼
腦海裏梳理一下請求的流程:FaceBoxView.PointClick->FaceBoxViewModel.OnClick()->委託給外部的某個Handler。
實際上『委託』這個概念很是重要,和具體的語言、平臺無關。好比在iOS開發常常聽到代理模式,顧名思義,將請求交給具體的處理者去處理。設計模式並不深奧,不少模式的理念都是相通的,不一樣的是對應語言下不一樣的表現形態,善於剖開現象看本質,不少都是相通的。
源代碼託管在Github上,點擊此瞭解
歡迎關注個人公衆號: