1. 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现。即:一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。

  2. 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。

  3. 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。

  • 抽象类(AbstractClass):实现了模板方法,定义了算法的骨架。

  • 具体类(ConcreteClass):实现抽象类中的抽象方法,已完成完整的算法。

    抽象方法:一个抽象方法由抽象类声明,由具体子类实现。在Java语言里抽象方法以abstract关键字标示。

    模板方法 一 个模板方法是定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。

实例:在Android中,往往会有一些全局的基类,包括BaseActivity,BaseFragment等等,
用于规范整个程序的View层的代码风格,此时,即可充分运用到模板方法模式
public abstract class IBaseActivity extends Activity{/**
     * 模板方法,用于返回布局ID
     */
    public abstract int initLayout();

    /**
     * 模板方法,初始化View
     * final方法必须有执行体
     * 和抽象方法是有区别
     */
    public final void initView(){setColor();
    };

    public void setColor(){}/**
     * 模板方法,获取数据,执行耗时操作
     */
    protected abstract void requestData();

    /**
     * 提供给子类动态设置状态栏颜色
     */
    protected void setSystemBarColor(int colorId) {}//...省略一体化状态栏处理

    /**
     * 该方法在onCreate中执行,用于获取Fragment的参数传递
     * 子类可按情况自行选择复写
     */
    protected void getArgs() {}
public class MainActivity extends IBaseActivity {@Override
    protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }@Override
    public int initLayout() {return 0;
    }@Override
    protected void requestData() {}
}
总结:
一个抽象类,一个实现类,抽象类里面放一个final的方法.
  • 父类中控制流程的方法定义为Final
  • 父类中提供一系列子类可复写的方法,从而将具体步骤中的实现延迟到子类中

从上面可以看出,BaseActivity中的Oncrea()方法被定义为Final,所以子类是无法重写的,这样可以很好的避免子类复写导致执行流程被打乱.由于父类中流程已经定义好,子类只需要负责具体实现的步骤即可,这样代码结构非常清晰,且不容易出错.

安卓代码中用到的地方:

1.View的绘制

2.AsyncTask

public abstract class AsyncTask<Params, Progress, Result> {private static final String LOG_TAG = "AsyncTask";

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    // We want at least 2 threads and at most 4 threads in the core pool,
    // preferring to have 1 less than the CPU count to avoid saturating
    // the CPU with background work
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }};

    private static final BlockingQueue<Runnable> sPoolWorkQueue =new LinkedBlockingQueue<Runnable>(128);

    /**
     * An {@link Executor} that can be used to execute tasks in parallel.
     */
    public static final Executor THREAD_POOL_EXECUTOR;

    static {ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }
@MainThread
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;
}
@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {return executeOnExecutor(sDefaultExecutor, params);
}

模板方法是一种代码复用的基本技术。它们在类库中尤为重要,它们提取了类库中的公共行为。

相当于继承一样!,父类调用子类去干什么事情
打比方说父亲有很多理想,就行医救人吧,但是父亲医术不行,只能靠儿子,儿子长大后遵从父亲大志,春风拂面,妙手回春,实现了父亲的理想,儿子做的事情早在出生前就定下来了,是父亲之前久定好的模板。
认识到模板方法的这种思想,父类可以让未知的子类去做它本身可能完成的不好或者根本完成不了的事情,对框架学习大有帮助。
别调用我们,我会调用你
(就好比猎头和求职者,求职者不需要去找猎头,猎头只要有工作就会找到你)称之为好莱坞原则

  1. 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现。即:一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。

  2. 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。

  3. 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。

  • 抽象类(AbstractClass):实现了模板方法,定义了算法的骨架。

  • 具体类(ConcreteClass):实现抽象类中的抽象方法,已完成完整的算法。

    抽象方法:一个抽象方法由抽象类声明,由具体子类实现。在Java语言里抽象方法以abstract关键字标示。

    模板方法 一 个模板方法是定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。

实例:在Android中,往往会有一些全局的基类,包括BaseActivity,BaseFragment等等,
用于规范整个程序的View层的代码风格,此时,即可充分运用到模板方法模式
public abstract class IBaseActivity extends Activity{
/**
     * 模板方法,用于返回布局ID
     */
    public abstract int initLayout();

    /**
     * 模板方法,初始化View
     * final方法必须有执行体
     * 和抽象方法是有区别
     */
    public final void initView(){
setColor();
    };

    public void setColor(){
}
/**
     * 模板方法,获取数据,执行耗时操作
     */
    protected abstract void requestData();

    /**
     * 提供给子类动态设置状态栏颜色
     */
    protected void setSystemBarColor(int colorId) {
}
//...省略一体化状态栏处理

    /**
     * 该方法在onCreate中执行,用于获取Fragment的参数传递
     * 子类可按情况自行选择复写
     */
    protected void getArgs() {
}

public class MainActivity extends IBaseActivity {
@Override
    protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
@Override
    public int initLayout() {
return 0;
    }
@Override
    protected void requestData() {
}
}

总结:
一个抽象类,一个实现类,抽象类里面放一个final的方法.
  • 父类中控制流程的方法定义为Final
  • 父类中提供一系列子类可复写的方法,从而将具体步骤中的实现延迟到子类中

从上面可以看出,BaseActivity中的Oncrea()方法被定义为Final,所以子类是无法重写的,这样可以很好的避免子类复写导致执行流程被打乱.由于父类中流程已经定义好,子类只需要负责具体实现的步骤即可,这样代码结构非常清晰,且不容易出错.

安卓代码中用到的地方:

1.View的绘制

2.AsyncTask

public abstract class AsyncTask<Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask";

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    // We want at least 2 threads and at most 4 threads in the core pool,
    // preferring to have 1 less than the CPU count to avoid saturating
    // the CPU with background work
    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE_SECONDS = 30;

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
        }
};

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);

    /**
     * An {@link Executor} that can be used to execute tasks in parallel.
     */
    public static final Executor THREAD_POOL_EXECUTOR;

    static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }
@MainThread
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;
}

@MainThread
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}

模板方法是一种代码复用的基本技术。它们在类库中尤为重要,它们提取了类库中的公共行为。

相当于继承一样!,父类调用子类去干什么事情
打比方说父亲有很多理想,就行医救人吧,但是父亲医术不行,只能靠儿子,儿子长大后遵从父亲大志,春风拂面,妙手回春,实现了父亲的理想,儿子做的事情早在出生前就定下来了,是父亲之前久定好的模板。
认识到模板方法的这种思想,父类可以让未知的子类去做它本身可能完成的不好或者根本完成不了的事情,对框架学习大有帮助。
别调用我们,我会调用你
(就好比猎头和求职者,求职者不需要去找猎头,猎头只要有工作就会找到你)称之为好莱坞原则

Android 最常用的设计模式四 安卓源码分析——模板方法(Mould)相关推荐

  1. Android 9(P)之init进程启动源码分析指南之一

         Android 9 之init进程启动源码分析指南之一 Android 9 (P) 系统启动及进程创建源码分析目录: Android 9 (P)之init进程启动源码分析指南之一 Andro ...

  2. Android 9 (P)之init进程启动源码分析指南之三

          Android 9 (P)之init进程启动源码分析指南之三 Android 9 (P)系统启动及进程创建源码分析目录: Android 9 (P)之init进程启动源码分析指南之一 An ...

  3. Android 8.1/9.0 MTK Camera源码分析之录像快门声音控制流程

    前面已经针对拍照快门声音控制流程进行了分析,接下来分析一下录像快门声音的控制流程. Android 8.1/9.0 MTK Camera源码分析之快门声音控制流程 这两篇文章其实都是相对于手机系统RO ...

  4. Android 8.1/9.0 MTK Camera源码分析之快门声音控制流程

    Android 8.1/9.0 MTK Camera源码分析之快门声音控制 在Android 8.1上mtk camera有控制快门声音的接口,但是并没有了控制录像快门声音的接口.之所以会有这个现象, ...

  5. 【C++】Android (Light)RefBase-sp-wp引用计数-智能指针源码分析

    文章目录 1.RefBase简介 2.RefBase源码分析 3.RefBase使用注意事项 4.总结 1.RefBase简介 什么是RefBase?RefBase是Android中的一个C++类,用 ...

  6. 【Android Protobuf 序列化】Protobuf 使用 ( Protobuf 源码分析 | 创建 Protobuf 对象 )

    文章目录 一.Protobuf 源码分析 二.创建 Protobuf 对象 三.完整代码示例 四.参考资料 一.Protobuf 源码分析 Protobuf 源文件如下 : addressbook.p ...

  7. 解密android日志xlog,XLog 详解及源码分析

    一.前言 这里的 XLog 不是微信 Mars 里面的 xLog,而是elvishew的xLog.感兴趣的同学可以看看作者 elvishwe 的官文史上最强的 Android 日志库 XLog.这里先 ...

  8. Android SQLite多线程读写和线程同步源码分析

    没啥诀窍,只需保证几个线程都是用的一个SQLiteDataBase对象就行了. 如果我们非要在不同线程中用两个或更多的SQLiteDataBase对象呢,当然这些SQLiteDataBase对象所操作 ...

  9. 【Android CameraX】CameraXBasic —— 官方CameraX实例源码分析

    一.简介 二.源码分析 2.1 build.gradle 2.2 代码结构 2.3 变量 2.3.1 lensFacing 2.3.2 preview 2.3.3 Image capture 2.3. ...

  10. axios核心内容(四)源码分析

    axios之源码分析 1.源码目录结构 2.源码分析 (1)axios与Axios的关系 (2)instance与axios的区别 (3)axios运行的整体流程 (4)axios的请求/响应拦截器 ...

最新文章

  1. C++ 自由存储区是否等价于堆?
  2. RocketMQ:NameServer路由管理源码分析
  3. 计算机应用基础实训任务书,《计算机应用基础》任务书
  4. NYOJ 170 网络的可靠性
  5. Mybatis使用IN语句查询
  6. Makefile文件试错
  7. java 蓝桥杯算法训练 数组查找及替换
  8. [配置]VUE中通过process.env判断开发,测试和生产环境,并分环境配置不同的URL HOST
  9. php监控nginx,zabbix php nginx 监控搭建
  10. struts 1.x 原理
  11. 盐城计算机考试时间安排,2019盐城中考具体时间安排 什么时候考试
  12. 当想给下一个请求发送同享的数据时候 可以使用域对象设置属性
  13. 深入解密比Guava Cache更优秀的缓存-Caffeine
  14. 电商物流快递意外延误创意海报设计PSD格式,用心良苦
  15. 仿照elementUI编写自己的表单组件
  16. mysql 用户名唯一,mysql用户名和密码(mysql忘记用户名密码)
  17. SpringBoot 下载打包图片
  18. 亚马逊电商数据自动化管理接口平台JAVA SP-API接口开发(下)
  19. Unity 使用 Behaviac (二)让unity的行为能执行behaviac搭建的树的逻辑
  20. 人工智能 | 自动驾驶与人工智能前沿研究报告(人才篇)

热门文章

  1. 代码背景护眼色设置RGB
  2. css能不能实现剪切蒙版,CSS中图形剪切、遮罩功能-及使用说明
  3. SAP中计划日历计算规则的理解
  4. 繁体字生僻字数据库报错处理
  5. 首届技术播客月开播在即
  6. python re模块下载_python re模块
  7. mac 回车键、空格键失灵(非物理原因)解决方法
  8. 古体字与简体字对照表_简体字和繁体字对照表
  9. threejs开启对数深度缓存区时、着色器深度混乱
  10. java 转义符 输出,Java转义字符怎么输出的