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

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

这篇博文通过学习尚硅谷韩顺平老师《设计模式》课程所做,在此非常感谢!

概述

基本介绍

  • 模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern),在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行;
  • 简单说,模板方法模式 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤;
  • 这种类型的设计模式属于行为型模式;
  • 需要知道,模板发模式中的钩子方法:在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为钩子

细节和注意事项

  • 基本思想是:算法只存在于一个地方,也就是在父类中,容易修改。需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改;
  • 实现了最大化代码复用。父类的模板方法和已实现的某些步骤会被子类继承而直接使用;
  • 既统一了算法,也提供了很大的灵活性。父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步骤的实现;
  • 该模式的不足之处:每一个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大;
  • 一般模板方法都加上 final 关键字, 防止子类重写模板方法;
  • 模板方法模式使用场景:当要完成在某个过程,该过程要执行一系列步骤 ,这一系列的步骤基本相同,但其个别步骤在实现时 可能不同,通常考虑用模板方法模式来处理;

UML
在这里插入图片描述

问题引入

制作豆浆的程序,说明如下:

  • 任何豆浆的制作流程:选材 -> 添加配料 -> 浸泡 -> 放到豆浆机打碎
  • 通过添加不同的配料,可以制作出不同口味的豆浆;
  • 选材、浸泡、放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的,仅仅是添加配料的不同;

代码实现

UML

首先构建出UML图,如下所示
在这里插入图片描述

编码

首先创建模板类MakeSoybean,并提供给让子类实现的方法add()钩子函数isAdd()【判断是否执行add()方法】,不需要子类去覆盖的方法设置为private,模板方法修饰为final保证外部能调用这个模板方法完成业务并且不被子类覆盖破坏掉

package edu.hebeu.template.soybean;

/**
 * 模板类
 * @author 13651
 *
 */
public abstract class MakeSoybean {
	
	/**
	 * 这个方法用来做模板方法(添加关键字final,防止子类重写该方法),用来制作豆浆
	 */
	public final void make() {
		select();
		if(isAdd()) {
			add();
		}
		soak();
		beat();
	}
	
	/**
	 * 选择黄豆
	 */
	private void select() {
		System.out.println("选取适量的黄豆");
	}
	
	/**
	 * 添加配料的方法,交由子类(不同口味的豆浆具体实现)
	 */
	protected abstract void add();
	
	private void soak() {
		System.out.println("将材料浸泡");
	}
	
	private void beat() {
		System.out.println("将材料研磨,制出豆浆");
	}
	
	/**
	 * 这个方法默认实现,具体返回值交由子类决定,充当"钩子",即这个方法是"钩子方法"
	 * 
	 * 决定是否添加配料(即是否执行add()方法)
	 * @return
	 */
	protected boolean isAdd() {
		return true;
	}
	
}

让所有口味的豆浆类都继承上面的抽象类,但是需要注意根据需求决定钩子函数isAdd()的状态(如纯豆浆类是不需要添加任何配料的,所以我们要将isAdd()覆盖为false),如下三个类:、``

package edu.hebeu.template.soybean;

/**
 * 红枣味的豆浆
 * @author 13651
 * 
 */
public class JujubeSoybean extends MakeSoybean {

	@Override
	protected void add() {
		System.out.println("搭配适量红枣");
	}

}

package edu.hebeu.template.soybean;

/**
 * 牛奶味的豆浆
 * @author 13651
 *
 */
public class MilkSoybean extends MakeSoybean {

	@Override
	protected void add() {
		System.out.println("搭配适量的牛奶");
	}

}

package edu.hebeu.template.soybean;

/**
 * 制作纯豆浆
 * @author 13651
 *
 */
public class PureSoybean extends MakeSoybean {

	@Override
	protected void add() { // 因为纯豆浆不需要添加任何配料,所以将add()方法空实现
//		new UnsupportedOperationException(); // 抛出一个不支持操作的异常
	}

	@Override
	protected boolean isAdd() {
		return false;
	}
	
}

此时,模板方法模式的框架就搭建完成了,我们编写测试类进行测试

package edu.hebeu.template;

import edu.hebeu.template.soybean.JujubeSoybean;
import edu.hebeu.template.soybean.MakeSoybean;
import edu.hebeu.template.soybean.MilkSoybean;
import edu.hebeu.template.soybean.PureSoybean;

public class Client {
	public static void main(String[] args) {
		// 制作红枣豆浆
		System.out.println("-------------------------红枣豆浆---------------------------");
		MakeSoybean makeSoybean = new JujubeSoybean();
		makeSoybean.make();
		
		System.out.println(); System.out.println();
		
		// 制作牛奶豆浆
		System.out.println("-------------------------牛奶豆浆---------------------------");
		MakeSoybean makeSoybean2 = new MilkSoybean();
		makeSoybean2.make();
		
		System.out.println(); System.out.println();
		
		// 制作纯豆浆
		System.out.println("--------------------------纯豆浆--------------------------");
		MakeSoybean makeSoybean3 = new PureSoybean();
		makeSoybean3.make();
		
	}
}

测试

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值