5. 应用场景
- 一次性实现算法的执行顺序和固定不变部分,可变部分则交由子类来实现。
- 多个子类中拥有相同的行为时,可以将其抽取出来放在父类中,避免重复的代码。
- 使用钩子方法来让子类决定父类的某个步骤是否执行,实现子类对父类的反向控制。
- 控制子类扩展。模板方法只在特定点调用钩子方法,这样就只允许在这些点进行扩展。
6. 优点
- 提高代码复用性,去除子类中的重复代码。
- 提高扩展性,不同实现细节放到不同子类中,易于增加新行为。
7. 缺点
每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。
Android中的源码分析
Android中 View 的 draw 方法就是使用了模板方法模式:
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;
}
}
===================================================================
说明
View
的draw()
方法中定义了一整套的绘制流程,这个流程是固定的,所有的Android中的View
都是按照这个流程来绘制的。其中drawBackground()
这个方法在View
类中是实现了具体过程的,而onDraw()
方法和dispatchDraw()
方法在View
中都是空实现,即都是钩子方法。不同的子类通过重写这些空实现来实现自身不同的绘制效果。View
,像TextView
这些单一的View
,就会重写onDraw()
方法,由于TextView
没有子View
,所以dispatchDraw()
还是空实现;而ViewGroup
类含有子View
,需要遍历子View
并绘制,因此需要重写onDraw()
和dispatchDraw()
。onDraw()
;自定义ViewGroup
时则需要重写onDraw()
和dispatchDraw()
。
No comments:
Post a Comment