android 模板设计,Android的设计模式-模板方法模式
前言
Android的設計模式系列文章介紹,歡迎關注,持續更新中:
1.定義
定義一個操作中的算法框架,而將一些步驟延遲到子類中,使得子類可以不改變一個算法的結構即可重定義算法的某些特定步驟。
2.介紹
模板方法模式屬于行為型模式。
模板方法模式主要是用來定義一套流程下來的固定步驟,而具體的步驟實現則可以是不固定的。
3.UML類圖
模板方法UML類圖.jpg
角色說明:
AbstractClass(抽象類):,定義了一整套算法框架。
ConcreteClass(具體實現類):具體實現類,根據需要去實現抽象類中的方法。
4.實現
繼續以送快遞為例,快遞員送快遞基本就是一套固定的流程:收到快遞,準備派送->聯系收貨人->確定結果。
4.1 創建抽象類
定義算法框架,這里是快遞員派送快遞的步驟:
public abstract class Postman {//抽象快遞員類
//派送流程
public final void post() {//這里申明為final,不希望子類覆蓋這個方法,防止更改流程的執行順序
prepare();//準備派送
call();//聯系收貨人
if (isSign())//是否簽收
sign();//簽收
else refuse();//拒簽
}
protected void prepare() {//準備操作,固定流程,父類實現
System.out.println("快遞已達到,準備派送");
}
protected abstract void call();//聯系收貨人,聯系人不一樣,所以為抽象方法,子類實現
protected boolean isSign() {//是否簽收,這個是鉤子方法,用來控制流程的走向
return true;
}
protected void sign() {//簽收,這個是固定流程,父類實現
System.out.println("客戶已簽收,上報系統");
}
protected void refuse() {//拒簽,空實現,這個也是鉤子方法,子類可以跟進實際來決定是否去實現這個方法
}
}
需要注意的是上面的抽象類(Postman)包含了三種類型的方法:抽象方法、具體方法和鉤子方法。
抽象方法:需要子類去實現。如上面的call()。
具體方法:抽象父類中直接實現。如上面的prepare()和sign()。
鉤子方法:有兩種,第一種,它是一個空實現的方法,子類可以視情況來決定是否要覆蓋它,如上面的refuse();第二種,它的返回類型通常是boolean類型的,一般用于對某個條件進行判斷,如果條件滿足則執行某一步驟,否則將不執行,如上面的isSign()。
4.2 創建具體實現類
根據需要去實現抽象類中的方法,下面以派送給兩個不同的人為例,其中一個簽收,另一個拒收:
public class PostA extends Postman {//派送給A先生
@Override
protected void call() {//聯系收貨,實現父類的抽象方法
System.out.println("聯系A先生并送到門口");
}
}
public class PostB extends Postman {//派送給B先生
@Override
protected void call() {//聯系收貨,實現父類的抽象方法
System.out.println("聯系B先生并送到門口");
}
@Override
protected boolean isSign() {//是否簽收,覆蓋父類的鉤子方法,控制流程的走向
return false;
}
@Override
protected void refuse() {//拒簽,覆蓋父類的鉤子方法
System.out.println("拒絕簽收:商品不符");
}
}
4.3 客戶端測試
public void test(){
System.out.println("----派送A----");
Postman postA=new PostA();
postA.post();
System.out.println("----派送B----");
Postman postB=new PostB();
postB.post();
}
輸出結果:
----派送A----
快遞已達到,準備派送
聯系A先生并送到門口
客戶已簽收,上報系統
----派送B----
快遞已達到,準備派送
聯系B先生并送到門口
拒絕簽收:商品不符
5. 應用場景
一次性實現算法的執行順序和固定不變部分,可變部分則交由子類來實現。
多個子類中擁有相同的行為時,可以將其抽取出來放在父類中,避免重復的代碼。
使用鉤子方法來讓子類決定父類的某個步驟是否執行,實現子類對父類的反向控制。
控制子類擴展。模板方法只在特定點調用鉤子方法,這樣就只允許在這些點進行擴展。
6. 優點
提高代碼復用性,去除子類中的重復代碼。
提高擴展性,不同實現細節放到不同子類中,易于增加新行為。
7. 缺點
每個不同的實現都需要定義一個子類,這會導致類的個數的增加,設計更加抽象。
8. Android中的源碼分析
Android中View的draw方法就是使用了模板方法模式:
8.1 View的draw方法
public class View{
//鉤子方法,空實現
protected void onDraw(Canvas canvas) {
}
//鉤子方法,空實現
protected void dispatchDraw(Canvas canvas) {
}
//繪制方法,定義繪制流程
public void draw(Canvas canvas) {
//其他代碼略
/*
* 繪制流程如下:
*
* 1. 繪制view背景
* 2. 如果有需要,就保存圖層
* 3. 繪制view內容
* 4. 繪制子View
* 5. 如果有必要,繪制漸變框和恢復圖層
* 6. 繪制裝飾(滑動條等)
*/
if (!dirtyOpaque) {
drawBackground(canvas);//步驟1. 繪制view背景
}
// 如果可能的話跳過第2步和第5步(常見情況)
final int viewFlags = mViewFlags;
boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
if (!verticalEdges && !horizontalEdges) {
if (!dirtyOpaque) onDraw(canvas);//步驟3. 繪制view內容
dispatchDraw(canvas);//步驟4. 繪制子View
// 覆蓋一部分內容,繪制前景
if (mOverlay != null && !mOverlay.isEmpty()) {
mOverlay.getOverlayView().dispatchDraw(canvas);
}
onDrawForeground(canvas); //步驟6. 繪制裝飾(滑動條等)
return;
}
}
8.2 說明
View的draw()方法中定義了一整套的繪制流程,這個流程是固定的,所有的Android中的View都是按照這個流程來繪制的。其中drawBackground()這個方法在View類中是實現了具體過程的,而onDraw()方法和dispatchDraw()方法在View中都是空實現,即都是鉤子方法。不同的子類通過重寫這些空實現來實現自身不同的繪制效果。
具體的View,像TextView這些單一的View,就會重寫onDraw()方法,由于TextView沒有子View,所以dispatchDraw()還是空實現;而ViewGroup類含有子View,需要遍歷子View并繪制,因此需要重寫onDraw()和dispatchDraw()。
所以,我們自定義View時必須且只需重寫onDraw();自定義ViewGroup時則需要重寫onDraw()和dispatchDraw()。
8.3 其他
另外,像Activity的生命周期,AsyncTask等等也是用到了模板方法模式,也興趣的可以研究一下。
總結
以上是生活随笔為你收集整理的android 模板设计,Android的设计模式-模板方法模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 操作Word书签(二):添加文
- 下一篇: android sina oauth2.