到国美面试Android的时候,问我的设计模式相关的问题:
1、单例模式的意义时什么;
2、有哪几种工厂方法模式;
3、你用过的模板方法模式,举例说明;
自己感觉答的一塌糊涂。模板方法模式都没说出来;
悲剧!
基础不牢,地动山摇。
大公司注重基础,所以对于java 基础,设计模式,算法。这些是一定牢固的!
1、定义:
定义一个操作算法的骨架,将一些步骤延伸到子类中。
模版方法模式使得子类可以不改变算法结构即可重定义该算法的某些步骤。
Defines the skeleton of an algorithm in a method, deferring some steps to subclasses.
Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
2、作用:
通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中,在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。
3、模板类,模板方法:
3.1、模板类可以是抽象类,也可以是具体类,根据需要来确定。
3.2、模板类中的模板方法,一定是具体方法,其他方法可以使抽象方法也可以是具体方法;
3.3、通过继承与多态的控制,可以实现子类对父子的反向控制;
4、demo
package com.example.demo.TemplateMethod; import android.util.Log; /** * 模版方法抽象类 * @author qubian * @data 2015年6月9日 * @email naibbian@163.com * */ public abstract class TemplateLotteryAbs { /** * 获取随机数 */ protected abstract String getRandomNum(int num); /** * 处理随即数产生的数据 */ protected abstract void doLotteryString(String lottery); /** * 计算注数 */ protected abstract void doLotteryNum(); /** * 是否标红 * @return */ public boolean shouldSetStringRed() { return false; } /** * 标红 */ protected void SetStringRed() { Log.i("TemplateAbs", "SetStringRed"); } /** * 模板方法:定义在抽象类中,并由子类不加以修改地完全继承下来。 * 模板方法是一个具体方法,它给出了一个顶层逻辑框架, * 而逻辑的组成步骤在抽象类中可以是具体方法,也可以是抽象方法。 * 由于模板方法是具体方法,因此模板方法模式中的抽象层只能是抽象类,而不是接口。 * */ public void doInfo(int num) { // 内部控制 doLotteryString(getRandomNum(num)); doLotteryNum(); // 这可以通过 继承覆盖,反向控制父类的方法 if (shouldSetStringRed()) { SetStringRed(); } } }
具体方法:
package com.example.demo.TemplateMethod; import android.util.Log; /** * 模板方法子类 * @author qubian * @data 2015年6月9日 * @email naibbian@163.com * */ public class TemplateLottery extends TemplateLotteryAbs{ private static final String TAG ="TemplateObj"; @Override protected String getRandomNum(int num) { return "1,2,3,4,5,6"; } @Override protected void doLotteryString(String lottery) { Log.i(TAG, "doLotteryString"); } @Override protected void doLotteryNum() { } /** * 反向控制 */ @Override public boolean shouldSetStringRed() { return super.shouldSetStringRed(); } @Override protected void SetStringRed() { super.SetStringRed(); } }
使用:
package com.example.demo.TemplateMethod; /** * 使用 模板方法模式 * @author qubian * @data 2015年6月9日 * @email naibbian@163.com * */ public class UseTemplate { public void use() { TemplateLotteryAbs tempObj= new TemplateLottery(); tempObj.doInfo(5); } }
7、在Android中的运用:
在Android源码中,View中的Draw()方法就是一个“模板方法”。
当继承View子类中,如果要重写或者扩展这个方法时,整个方法流程和基本内容不能够修改,
View 视图的构建,都是由View自身实现,其中的算法实现流程都是确定的;
子类只能通过扩展onDraw(Canvas canvas)和dispatchDraw(Canvas canvas)两个函数,使子类自己的View显示效果和别的具体子类的不同。
其中有:TextView类中重写了OnDraw函数,ViewGroup类,SurfaceView重写了dispatchDraw()函数等等。
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource { /** * Implement this to do your drawing. * * @param canvas the canvas on which the background will be drawn */ protected void onDraw(Canvas canvas) { } /** * Called by draw to draw the child views. This may be overridden * by derived classes to gain control just before its children are drawn * (but after its own view has been drawn). * @param canvas the canvas on which to draw the view */ protected void dispatchDraw(Canvas canvas) { } }
public class TextView extends View implements ViewTreeObserver.OnPreDrawListener { @Override protected void onDraw(Canvas canvas) { restartMarqueeIfNeeded(); // Draw the background for this view super.onDraw(canvas); final Drawables dr = mDrawables; if (dr != null) { //..... } int color = mCurTextColor; mTextPaint.setColor(color); mTextPaint.drawableState = getDrawableState(); canvas.save(); }