Android设计模式之——模板方法模式

一、介绍

在面向对象开发过程中,通常会遇到这样的一个问题,我们知道一个算法所需的关键步骤,并确定了这些步骤的执行顺序,但是,某些步骤的具体实现是未知的,或者说某些步骤的实现是会随着环境的变化而改变的,例如,执行程序的流程大致如下:

  1. 检查代码的正确性;
  2. 链接相关的类库;
  3. 编译相关代码;
  4. 执行程序。

对于不同的程序设计语言,上述4个步骤都是不一样的,但是,它们的执行流程是固定的,这类问题的解决方案就是我们本章要讲的模板方法模式。

二、定义

定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

三、使用场景

  • 多个子类有公有的方法,并且逻辑基本相同时。

  • 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。

  • 重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为。

四、模板方法模式的UML类图

UML类图:

这里写图片描述

角色介绍:

  • AbstractClass:抽象类,定义了一套算法框架。

  • ConcreteClass1:具体实现类1。

  • ConcreteClass2:具体实现类2。

五、简单示例

模板方法实际上是封装一个固定流程,就像是一套执行模板一样,第一步该做什么,第二步该做什么都已经在抽象类中定义好。而子类可以有不同的算法实现,在框架不被修改的情况下实现某些步骤的算法替换,下面以打开计算机这个动作来简单演示一下模板方法。打开计算机的整个过程都是相对固定的,首先启动计算机电源,计算机检测自身状态没有问题时将进入操作系统,对用户进行验证之后即可登录计算机,下面我们使用模板方法来模拟一下这个过程:

抽象的 Computer

/*** 抽象的 Computer*/
public abstract class AbstractComputer {//下面是抽象方法,子类可以覆盖,不允许外部直接调用这些方法,所以用protected/*** 开启电源*/protected abstract void powerOn();/*** 检查硬件*/protected abstract void checkHardware();/*** 载入操作系统*/protected abstract void loadOS();/*** 登录*/protected abstract void login();//下面是钩子方法,声明并实现/*** 是否需要登录* * @return true为需要登录*/protected boolean isLogin(){return true;}//下面是模板方法,定义为final,子类不能覆盖此方法 /*** 启动计算机方法,步骤为开启电源、系统检查、加载系统、检查是否登录。*/public final void startUp(){System.out.println("--------开机 START--------");powerOn();checkHardware();loadOS();if(isLogin()){login();}System.out.println("-------- 开机 END --------");}}

Windows系统电脑(不需登录):

/*** Windows系统电脑*/
public class WindowsComputer extends AbstractComputer{@Overrideprotected void powerOn() {System.out.println("Windows电脑开启电源");}@Overrideprotected void checkHardware() {System.out.println("Windows电脑检查硬件");}@Overrideprotected void loadOS() {System.out.println("Windows电脑载入操作系统");}@Overrideprotected void login() {}@Overrideprotected boolean isLogin() {return false;//返回false,不需登录}}

Mac系统电脑(需登录):

/*** Mac系统电脑*/
public class MacComputer extends AbstractComputer{@Overrideprotected void powerOn() {System.out.println("Mac电脑开启电源");}@Overrideprotected void checkHardware() {System.out.println("Mac电脑检查硬件");}@Overrideprotected void loadOS() {System.out.println("Mac电脑载入操作系统");}@Overrideprotected void login() {System.out.println("Mac电脑登录");}}

调用:

public class Client {public static void main(String[] args) {AbstractComputer comp = new WindowsComputer();comp.startUp();comp = new MacComputer();comp.startUp();}
}

结果:

--------开机 START--------
Windows电脑开启电源
Windows电脑检查硬件
Windows电脑载入操作系统
-------- 开机 END --------
--------开机 START--------
Mac电脑开启电源
Mac电脑检查硬件
Mac电脑载入操作系统
Mac电脑登录
-------- 开机 END --------

六、Android源码中的模板方法模式

1、AsyncTask

在使用AsyncTask时,我们都知道把耗时操作放到doInBackground(Params… params)中,在doInBackground之前,如果想做一些初始化操作,可以把实现写在onPreExecute中,当doInBackground执行完后会执行onPostExecute方法,而我们只需要构建AsyncTask对象,然后执行execute方法。

2、Activity的生命周期

ActivityThread的main函数被调用后,依次执行Activity的onCreate、onStart、onResume函数,用户通常在Activity的子类中覆写onCreate方法,并且在该方法中调用setContentView来设置布局。

七、区别

  • 工厂方法是模板方法的一种特殊版本。

  • 策略模式和模板方法模式都是封装算法,一个用组合,一个用继承。

  • 策略模式和模板模式通常可以互相替换。它们都像试卷,策略模式是选择题,模板模式是填空题。

八、总结

模板方法模式用4个字概括就是:流程封装。也就是把某个固定的流程封装到一个final方法中,并且让子类能够定制这个流程中的某些或者所有步骤,这就要求父类提取公用的代码,提升代码的复用率,同时带来了更好的可扩展性。

优点:

  • 封装不变部分,扩展可变部分。

  • 提取公共部分代码,便于维护。

缺点:

  • 需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合桥接模式来进行设计。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/447005.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android设计模式之——访问者模式

一、介绍 访问者模式是一种将数据操作与数据结构分离的设计模式,它是《设计模式》中23种设计模式中最复杂的一个,但它的使用频率并不高,正如《设计模式》的作者GOF对访问者模式的描述:大多数情况下,你不需要使用访问者…

C++类模板template <class T>简单使用方法

一个简单的例子 两个数比大小 如果两个数都是int类型 class Compare_int { public :Compare(int a,int b){xa;yb;}int max( ){return (x>y)?x:y;}int min( ){return (x<y)?x:y;} private :int x,y; }; 如果两个数是float类型 class Compare_float { public :Compare(…

Android设计模式之——中介者模式

一、介绍 中介者模式&#xff08;Mediator Pattern&#xff09;也称为调解者模式或调停者模式&#xff0c;Mediator本身就有调停者和调解者的意思。 在日常生活中调停者或调解者这个角色我们见得比较多的是“和事老”&#xff0c;也就是说调解两个有争端的人的角色&#xff0…

C++智能指针中unique_ptr部分内容的讲解

参考链接 std::unique_ptr 介绍 定义位于头文件<memory>std::unique_ptr 是通过指针占有并管理另一对象&#xff0c;并在 unique_ptr 离开作用域时释放该对象的智能指针。 在下列两者之一发生时用关联的删除器释放对象&#xff1a;1&#xff0c;销毁了管理的 unique_pt…

Java基础——Java多线程中sleep()、wait()和notify()

一、sleep()sleep()方法源码&#xff1a;/** * Causes the currently executing thread to sleep (temporarily cease * execution) for the specified number of milliseconds, subject to * the precision and accuracy of system timers and schedulers. The thread * does …

Key_handle的学习

代码 一切尽在不言中 #pragma once#include "common/common.h" #include "sdf/sdf.h"#include <memory>namespace sdf {namespace algorithm {class KeyHandle {public:using erased_internal_data_t char; //使用erased_internal_data_t等效于ch…

Java基础——虚拟机结构

一、Java平台结构图二、JVM、JRE和JDK关系JVM&#xff1a;Java Virtual Machine&#xff08;Java虚拟机&#xff09;&#xff0c;负责执行符合规范的Class文件 JRE&#xff1a; Java Runtime Environment &#xff08;java运行环境&#xff09;&#xff0c;包含JVM和类库 JDK&a…

解决 SSH Connection closed by foreign host 问题

用 Xshell 连接服务器总是报错 : Connection closed by foreign host.Disconnected from remote host... 原因可能是 SSH 服务器没设置保活时间间隔 , 具体设置如下 : 操作 # vim /etc/ssh/sshd_config 添加两行 , 或去掉注释 : ClientAliveInterval 60ClientAliveCountMax…

Java基础——synchronized

synchronized重要&#xff01;重要&#xff01;重要&#xff01;重要的事情说三遍&#xff0c;一定要记下来哦。 Java语言的关键字&#xff0c;当它用来修饰一个方法或者一个代码块的时候&#xff0c;能够保证在同一时刻最多只有一个线程执行该段代码。一、当两个并发线程访问同…

C++:MAC安装Boost库文件并且使用CLion开发

boost的filestem库 C在17版本的标准库中引入了一个filesystem库&#xff0c;用来处理文件路径&#xff0c;以及文件访问。很多编译器对filesystem库的支持还不是很好。为了解决这个问题&#xff0c;可以临时使用boost::filesystem来替代。其实C17标准中的filesystem库就是从bo…

Java基础——Java异常处理机制

一、引言 try…catch…finally恐怕是大家再熟悉不过的语句了&#xff0c;而且感觉用起来也是很简单&#xff0c;逻辑上似乎也是很容易理解。不过&#xff0c;我亲自体验的“教训”告诉我&#xff0c;这个东西可不是想象中的那么简单、听话。不信&#xff1f;那你看看下面的代码…

clion在使用sqlite3的时候,显示Undefined symbols for architecture x86_64错误的解决办法

显示Undefined symbols for architecture x86_64错误的原因 1、缺少静态库 环境&#xff1a;在模拟器上报错但在真机上能运行成功&#xff0c;而且报的错误来自于第三方库。原因&#xff1a;architecture x86_64 是指模拟器的架构&#xff0c;意思就是 Crypto 变量在模拟器架…

Java基础——Java反射机制及IoC原理

一、概念 主要是指程序可以访问&#xff0c;检测和修改它本身状态或行为的一种能力&#xff0c;并能根据自身行为的状态和结果&#xff0c;调整或修改应用所描述行为的状态和相关的语义。在java中&#xff0c;只要给定类的名字&#xff0c; 那么就可以通过反射机制来获得类的所…

Ubuntu boost库文件安装编译

简单介绍 Boost库是为C语言标准库提供扩展的一些C程序库的总称&#xff0c;由Boost社区组织开发、维护.Boost向来有准标准库之称&#xff0c;很多新特性例如智能指针等都是先在boost中实现&#xff0c;后来被吸收到标准库之中. Boost实现了日志、算法、日期、地理、数学、线程…

Java基础——类加载机制及原理

一、什么是类的加载&#xff1f; 类的加载指的是将类的.class文件中的二进制数据读入到内存中&#xff0c;将其放在运行时数据区的方法区内&#xff0c;然后在堆区创建一个java.lang.Class对象&#xff0c;用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Cl…

在Ubuntu环境下使用vcpkg安装sqlite_orm包文件

Ubuntu安装vcpkg 从github下载vcpkg的安装包&#xff0c;在usr/local路径下面执行如下命令 git clone https://github.com/Microsoft/vcpkg.git cd vcpkg //进入源码目录 ./bootstrap-vcpkg.sh //执行./bootstrap-vcpkg.sh进行编译安装&#xff0c;这个过程很慢 编译安装好…

finally语句与return语句的执行顺序

网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行&#xff1f;很多人都说不是&#xff0c;当然他们的回答是正确的&#xff0c;经过我试验&#xff0c;至少有两种情况下finally语句是不会被执行的&#xff1a; try语句没有被执行到…

window电脑查看ssh公钥,以及将自己的公钥添加到Github等类似网站

查看本机的ssh公钥 使用命令 cd ~/.ssh使用命令 ls 可以看到 id_rsa id_rsa.pub known_hosts 三个文件&#xff0c;此处需要的是id_rsa.pub文件使用命令 cat id_rsa.pub 查看文件的内容拷贝这段内容 添加自己的公钥 进入账户的设置页面参照如下步骤&#xff0c;进入SSH Key…

java八大排序算法

一、概述 排序有内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一次不能容纳全部的排序记录&#xff0c;在排序过程中需要访问外存。 我们这里说说八大排序就是内部排序。 当n较大&#xff0c;则应采…

密钥安全性讨论之密钥分层管理结构

密钥分层管理结构 密钥的安全管理通常采用层次化的保护方法。密钥管理分层管理机制将密钥分为三层&#xff0c;即根密钥、密钥加密密钥和工作密钥下层密钥为上层密钥提供加密保护&#xff0c;采用分层的密钥结构有助于密钥的管理满足本规范的要求 工作密钥 工作密钥对本地保存…