1. 模式简介
定义一个程序的整体流程,并允许子类为其中的一个或者多个步骤提供具体实现。模板方法使得子类可以在不改变整体流程的情况下,重新定义其中的某些步骤。属于行为型设计模式。
2. 示例代码
这里我们通过模板方法模式实现一个短信发送、邮件发送的 demo。
- 定义一个整体流程
/**
* <p>
* 消息发送器
* </p>
*
* @author yangkai.shen
* @date Created in 2019/11/18 17:22
*/
public abstract class BaseMessageSender {
/**
* 发送消息
*
* @param content 内容
*/
public void send(String content) {
validate(content);
if (!execute(content)) {
error(content);
}
}
/**
* 校验消息
*
* @param content 数据
*/
protected abstract void validate(String content);
/**
* 发送消息
*
* @param content 数据
* @return {@code true} - 发送成功,{@code false} - 发送失败
*/
protected abstract boolean execute(String content);
/**
* 错误记录
*
* @param content 数据
*/
protected abstract void error(String content);
}
- 短信发送的具体实现
/**
* <p>
* 短信发送器
* </p>
*
* @author yangkai.shen
* @date Created in 2019/11/18 17:40
*/
public class SmsSender extends BaseMessageSender {
/**
* 校验消息
*
* @param content 数据
*/
@Override
protected void validate(String content) {
if (content == null || "".equals(content.trim()) || content.trim().length() != 11) {
throw new RuntimeException("手机号码不合法");
}
}
/**
* 发送消息
*
* @param content 数据
* @return {@code true} - 发送成功,{@code false} - 发送失败
*/
@Override
protected boolean execute(String content) {
Random random = new Random();
if (random.nextInt(10) % 2 == 0) {
System.out.println("短信发送成功!");
return true;
} else {
return false;
}
}
/**
* 错误记录
*
* @param content 数据
*/
@Override
protected void error(String content) {
System.err.println("短信发送失败!手机号:" + content);
}
}
- 邮件发送的具体实现
/**
* <p>
* 邮件发送器
* </p>
*
* @author yangkai.shen
* @date Created in 2019/11/18 17:34
*/
public class EmailSender extends BaseMessageSender {
/**
* 校验消息
*
* @param content 数据
*/
@Override
protected void validate(String content) {
if (content == null || "".equals(content.trim())) {
throw new RuntimeException("数据不能为空");
}
}
/**
* 发送消息
*
* @param content 数据
* @return {@code true} - 发送成功,{@code false} - 发送失败
*/
@Override
protected boolean execute(String content) {
Random random = new Random();
if (random.nextInt(10) % 2 == 0) {
System.out.println("邮件发送成功!");
return true;
} else {
return false;
}
}
/**
* 错误记录
*
* @param content 数据
*/
@Override
protected void error(String content) {
System.err.println("邮件发送失败!发送内容:" + content);
}
}
- 测试类
/**
* <p>
* 模板模式,测试类
* </p>
*
* @author yangkai.shen
* @date Created in 2019/11/18 17:10
*/
public class PatternTest {
public static void main(String[] args) {
// 邮件发送
EmailSender emailSender = new EmailSender();
emailSender.send("测试内容");
// 短信发送
SmsSender smsSender = new SmsSender();
smsSender.send("17312341234");
}
}
- 测试结果
邮件发送失败!发送内容:测试内容
短信发送成功!
3. UML 图例
4. 应用
// Spring Data 这个模块下存在特别多的应用
// 比如:
// JdbcTemplate、RedisTemplate、MongoTemplate、ElasticsearchTemplate
5. 场景
-
一次性实现一个算法的主体流程的部分,并将可变的行为留给子类来实现。
-
各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复。
6. 优缺点
优点: 1、提高代码的复用性。2、提高代码的扩展性。3、符合开闭原则。
缺点: 1、导致类的数目增加。2、间接地增加了系统实现的复杂度。3、继承关系存在自身缺点,如果父类添加了新的抽象方法,所有子类都需要重新改一遍。