1.解决特定的问题,管理Activity,单例设计模式,recyclerview 添加头部和底部,装饰设计模式java
2.有利于代码的规范,让代码更灵活android
3.有利于咱们的开发,提升开发效率。git
我的理解:玩一些套路,23种程序员
通俗点的理解就是 :完成一件事情,有固定的数个步骤,可是每一个步骤根据对象的不一样,而实现细节不一样;就能够在父类中定义一个完成该事情的总方法,按照完成事件须要的步骤去调用其每一个步骤的实现方法。每一个步骤的具体实现,由子类完成。
github
package com.dp.example.templatemethod;
/**
* 抽象的Computer
* @author wulafu
*
*/
public abstract class AbstractComputer {
protected void powerOn() {
System.out.println("开启电源");
}
protected void checkHardware() {
System.out.println("硬件检查");
}
protected void loadOS() {
System.out.println("载入操做系统");
}
protected void login() {
System.out.println("小白的电脑无验证,直接进入系统");
}
/**
* 启动电脑方法, 步骤固定为开启电源、系统检查、加载操做系统、用户登陆。该方法为final, 防止算法框架被覆写.
*/
public final void startUp() {
System.out.println("------ 开机 START ------");
powerOn();
checkHardware();
loadOS();
login();
System.out.println("------ 开机 END ------");
}
}
package com.dp.example.templatemethod;
/**
* 码农的计算机
*
* @author wulafu
*/
public class CoderComputer extends AbstractComputer {
@Override
protected void login() {
System.out.println("码农只须要进行用户和密码验证就能够了");
}
}
package com.dp.example.templatemethod;
/**
* 军用计算机
*
* @author wulafu
*/
public class MilitaryComputer extends AbstractComputer {
@Override
protected void checkHardware() {
super.checkHardware();
System.out.println("检查硬件防火墙");
}
@Override
protected void login() {
System.out.println("进行指纹之别等复杂的用户验证");
}
}
package com.dp.example.templatemethod;
public class Test {
public static void main(String[] args) {
AbstractComputer comp = new CoderComputer();
comp.startUp();
comp = new MilitaryComputer();
comp.startUp();
}
}复制代码
------ 开机 START ------
开启电源
硬件检查
载入操做系统
码农只须要进行用户和密码验证就能够了
------ 开机 END ------
------ 开机 START ------
开启电源
硬件检查
检查硬件防火墙
载入操做系统
进行指纹之别等复杂的用户验证
------ 开机 END ------复制代码
经过上面的例子能够看到,在startUp方法中有一些固定的步骤,依次为开启电源、检查硬件、加载系统、用户登陆四个步骤,这四个步骤是电脑开机过程当中不会变更的四个过程。可是不一样用户的这几个步骤的实现可能各不相同,所以他们能够用不一样的实现。而startUp为final方法,即保证了算法框架不能修改,具体算法实现却能够灵活改变。startUp中的这几个算法步骤咱们能够称为是一个套路,便可称为模板方法。所以,模板方法是定义一个操做中的算法的框架,而将一些步骤延迟到子类中。使得子类能够不改变一个算法的结构便可重定义该算法的某些特定步骤。如图 :面试
在Android中,使用了模板方法且为咱们熟知的一个典型类就是AsyncTask了,关于AsyncTask的更详细的分析请移步Android中AsyncTask的使用与源码分析,咱们这里只分析在该类中使用的模板方法模式。算法
在使用AsyncTask时,咱们都有知道耗时的方法要放在doInBackground(Params... params)中,在doInBackground以前若是还想作一些相似初始化的操做能够写在onPreExecute方法中,当doInBackground方法执行完成后,会执行onPostExecute方法,而咱们只须要构建AsyncTask对象,而后执行execute方法便可。咱们能够看到,它整个执行过程实际上是一个框架,具体的实现都须要子类来完成。并且它执行的算法框架是固定的,调用execute后会依次执行onPreExecute,doInBackground,onPostExecute,固然你也能够经过onProgressUpdate来更新进度。咱们能够简单的理解为以下图的模式 :设计模式
下面咱们看源码,首先咱们看执行异步任务的入口, 即execute方法 :数组
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}
mStatus = Status.RUNNING;
onPreExecute();
mWorker.mParams = params;
exec.execute(mFuture);
return this;
}
复制代码
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return postResult(doInBackground(mParams));
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
final Result result = get();
postResultIfNotInvoked(result);
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
}
}
};
}
复制代码
简单的说就是mFuture就包装了这个mWorker对象,会调用mWorker对象的call方法,而且将之返回给调用者。关于AsyncTask的更详细的分析请移步Android中AsyncTask的使用与源码分析,咱们这里只分析模板方法模式。总之,call方法会在子线程中调用,而在call方法中又调用了doInBackground方法,所以doInBackground会执行在子线程。doInBackground会返回结果,最终经过postResult投递给UI线程。 咱们再看看postResult的实现 :ruby
private Result postResult(Result result) {
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
private static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult result = (AsyncTaskResult) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
复制代码
能够看到,postResult就是把一个消息( msg.what == MESSAGE_POST_RESULT)发送给sHandler,sHandler类型为InternalHandler类型,当InternalHandler接到MESSAGE_POST_RESULT类型的消息时就会调用result.mTask.finish(result.mData[0])方法。咱们能够看到result为AsyncTaskResult类型,源码以下 :
@SuppressWarnings({"RawUseOfParameterizedType"})
private static class AsyncTaskResult<Data> {
final AsyncTask mTask;
final Data[] mData;
AsyncTaskResult(AsyncTask task, Data... data) {
mTask = task;
mData = data;
}
}
复制代码
能够看到mTask就是AsyncTask对象,调用AsyncTask对象的finish方法时又调用了onPostExecute,这个时候整个执行过程就完成了。 总之,execute方法内部封装了onPreExecute, doInBackground, onPostExecute这个算法框架,用户能够根据本身的需求来在覆写这几个方法,使得用户能够很方便的使用异步任务来完成耗时操做,又能够经过onPostExecute来完成更新UI线程的工做。
另外一个比较好的模板方法示例就是Activity的声明周期函数,例如Activity从onCreate、onStart、onResume这些程式化的执行模板,这就是一个Activity的模板方法。
接下来咱们看一下怎么才能用到开发中... 等等我要去举报你 --> 怎么啦? 你抄袭别人的。怎么?被发现了吗,我这不是抄袭只是把好东西拿出来与你们分享而已,给你们推荐一下:github.com/simple-andr… 里面有不少设计模式,最好你们能够买一本书看一下这么好的东西仍是支持一下吧但愿能够出一些更好的(虽然我看的是电子文档)。说到这里很是感谢你们的打赏虽然很少可是我心里真的很感谢,但愿之后能够出更多好的文章。
在网上查了不少关于别人讲的模板设计模式,都是只简单的介绍一下概念而后写一个小的事例如:程序员的一天,银行办理业务等等等等。我最近剃了个光头,由于上班闲来无事看别人的博客的时候总是抓头发,一直都在想一想我该用到哪里呢?哪里又能用到呢?.......因此干脆剃了个光头。
由于目前仍是停留在内涵段子项目的系统架构部分,并且每一个项目确定离不开Activity,在Activity的onCreate()方法里面基本都是:设置布局 ->初始化头部 -> 初始化界面 -> 初始化数据。若是按照这么个流程是否是恰好符合咱们模板设计模式。
/** * Created by wulafu on 2019/2/8. * Description: 整个应用的BaseActivity */
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView();
initTitle();
initView();
initData();
}
// 初始化数据
protected abstract void initData();
// 初始化界面
protected abstract void initView();
// 设置界面视图
protected abstract void setContentView();
// 初始化头部
protected abstract void initTitle();
}
复制代码
之后咱们每次新建Activity就不会直接继承自 AppCompatActivity 而是咱们本身的BaseActivity就会自动要咱们复写BaseActivity里面的几个抽象方法,咱们在方法里面写对应的代码。
/** * Created by wulafu on 2019/2/8. * Description: 主页面MainActivity */
public class MainActivity extends BaseActivity {
@Override
protected void initData() {
}
@Override
protected void initView() {
}
@Override
protected void setContentView() {
setContentView(R.layout.activity_main);
}
@Override
protected void initTitle() {
}
}
复制代码
这也没见到什么好处啊~好处我待会再来讲,咱们先对BaseActivity来扩展一下,一些通用的流程和功能其实能够放在BaseActivity里面,好比前几回所分享的本身动手打造一套IOC注解框架、启动Activity...
/** * Created by wulafu on 2019/2/8. * Description: 整个应用的BaseActivity */
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView();
// IOC注解注入
ViewUtils.inject(this);
initTitle();
initView();
initData();
}
// 初始化数据
protected abstract void initData();
// 初始化界面
protected abstract void initView();
// 设置界面视图
protected abstract void setContentView();
// 初始化头部
protected abstract void initTitle();
/** * 启动一个Activity * @param activity 须要启动的Activity的Class */
public void startActivity(Class<? extends Activity> activity) {
Intent intent = new Intent(this,activity);
startActivity(intent);
}
/** * findViewById 不须要再去强转 */
public <T extends View> T viewById(@IdRes int resId) {
return (T) super.findViewById(resId);
}
}
复制代码
接下来咱们来讲一下好处,模板设计模式的好处就不说了网上太多了,咱们就只说在真正的开发中这么作的好处
做为一名java程序员,建立线程是工做中常常干的事情,也是面试中常常被提问的问题。你们都知道java中建立线程有两种最基本的方式: 建立Thread类; 实现runnable借口; 这两种方式有一个共同点就是咱们的业务逻辑必需要实现run()这个方法,而后咱们调用start()方法来启动线程。跟踪Thread的start()方法源码咱们能够看到:
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads * and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
复制代码
start()方法调用了一个start0()方法,而start0()方法源码以下:
private native void start0();
/**
* If this thread was constructed using a separate
* <code>Runnable</code> run object, then that
* <code>Runnable</code> object's <code>run</code> method is called; * otherwise, this method does nothing and returns. * <p> * Subclasses of <code>Thread</code> should override this method. * * @see #start() * @see #stop() * @see #Thread(ThreadGroup, Runnable, String) */ @Override public void run() { if (target != null) { target.run(); } }复制代码
start0是一个native修饰的方法,并且它调用了run(),其实一点从设计模式上不能理解,这里用到的就是一个简单的模板模式,目的就是为了让业务的逻辑和线程的逻辑分离。如下是模板模式模拟线程的实现,但愿有助于理解模板模式在Thread中的应用
/**
* Description
* <p>
* </p>
* DATE 2019/10/1.
*
* @author wulafu.
*/
public class Template {
public Template() {
}
public final void start(){
System.out.println("stat方法启动!");
run();
System.out.println("start方法结束!");
}
public void run(){}
public static void main(String[] args) {
Template template = new Template(){
@Override
public void run() {
System.out.println("run方法开始运行!");
}
};
template.start();
}
复制代码
运行结果:
stat方法启动!run方法开始运行!start方法结束!