模板模式可以理解成步骤模式,加入做成一件事情可以有清晰的步骤可循,这件事情就可以套用模板模式来实现。模板的概念应该很多同学都很熟悉,写一个简历,写一篇论文,假如有一个模板供我们参考的话,写起来就会更加容易,更加得心应手。这个简历模板和论文模板就可以认为是指定了写简历和写论文的步骤,我们只要按照这个步骤一步步编写即可。
模板模式的UML类图如下:
这里我们通过一个生活中的实例,炒菜来讲解一下如何使用模板模式。对于新手来说,炒菜就是按照一步步的步骤来的,大致可以分为 生火-加入食用油-加入菜-加入佐料-装盘 这几个步骤。通过代码来一一实现,首先新建一个抽象类,作为模板类:
AbstractCookTemplate.java(对应类图中的AbstractClass):
package com.template.demo;
public abstract class AbstractCookTemplate {
public final void cook(){
System.out.println("--------开始做饭-----------");
fire();//生火
oil();//倒入油
chaocai();//炒菜
zuoliao();//加佐料
zhuangpan();//装盘
System.out.println("--------结束做饭-----------");
}
protected void zhuangpan() {//设置权限protected,方便子类覆写
System.out.println("装盘");
}
protected void zuoliao() {
System.out.println("加入佐料");
}
protected void chaocai() {
System.out.println("炒菜");
}
protected void oil() {
System.out.println("加入油");
}
protected void fire() {
System.out.println("生火");
}
}
有些英文比较难,鉴于楼主英文水平有限就用拼音代替了,实际开发中这种方式不可取。
实现类-CookChicken.java(对应ConcreteClassA):
package com.template.demo;
public class CookChicken extends AbstractCookTemplate {
@Override
protected void chaocai() {
System.out.println("炒鸡肉");
}
}
实现类-CookFish.java(对应ConcreteClassB):
package com.template.demo;
public class CookFish extends AbstractCookTemplate {
@Override
protected void zhuangpan() {
System.out.println("鱼要装入大盘");
}
}
测试类:
package com.template.demo;
public class TestClass {
public static void main(String[] args) {
AbstractCookTemplate abstractCookTemplate=new CookChicken();
abstractCookTemplate.cook();
AbstractCookTemplate abstractCookTemplate2=new CookFish();
abstractCookTemplate2.cook();
}
}
运行测试类:
例子比较牵强,嗯哼,大家理解即可。话说又有人说了,假如要凉拌个黄瓜,不需要生火,这时该怎么办呢?
这时我们可以使用钩子方法来实现,具体是什么样的钩子,可以参照代码:
AbstractCookTemplate.java(对应类图中的AbstractClass):
package com.template.demo;
public abstract class AbstractCookTemplate {
public final void cook(){
System.out.println("--------开始做饭-----------");
if(!isColdFood()){
fire();//生火
}
oil();//倒入油
chaocai();//炒菜
zuoliao();//加佐料
zhuangpan();//装盘
System.out.println("--------结束做饭-----------");
}
protected boolean isColdFood() {//作为钩子
return false;
}
protected void zhuangpan() {//设置权限protected,方便子类覆写
System.out.println("装盘");
}
protected void zuoliao() {
System.out.println("加入佐料");
}
protected void chaocai() {
System.out.println("炒菜");
}
protected void oil() {
System.out.println("加入油");
}
protected void fire() {
System.out.println("生火");
}
}
我们可以看出在生火实现之前先进行判断,若是不是凉拌才允许生火方法。默认是生火的。
若不需要生火方法,在实现类中覆写isColdFood()方法,返回true即不运行fire()方法。
这时我们实现一个实现类,凉拌黄瓜如下:
package com.template.demo;
public class CookCucumber extends AbstractCookTemplate {
@Override
protected boolean isColdFood() {
return true;
}
}
在测试类中添加 凉拌黄瓜的实现:
package com.template.demo;
public class TestClass {
public static void main(String[] args) {
AbstractCookTemplate abstractCookTemplate=new CookChicken();
abstractCookTemplate.cook();
AbstractCookTemplate abstractCookTemplate2=new CookFish();
abstractCookTemplate2.cook();
AbstractCookTemplate abstractCookTemplate3=new CookCucumber();
abstractCookTemplate3.cook();
}
}
然后运行实例:
这时可以看出来,最后一个生活的方法没有运行,同理,可以用 钩子方法 决定其他方法是否运行,这样我们的模板将会更加灵活,应对各种需求。
喜欢的朋友请关注我和我的微信平台。