设计模式系列往期精彩文章
无场景,不设计,有这样的一个需求:有一个小贩需要制作豆浆,制作豆浆的流程如下:
-
制作豆浆的流程 选材—>添加配料—>浸泡—>放到豆浆机打碎 -
通过添加不同的配料,可以制作出不同口味的豆浆 -
选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的
请使用 模板方法模式 完成
废话不多说,直接步入正题。
模板方法模式
基本概念
模板方法模式(Template Method Pattern)又叫模板模式(Template Pattern),在一个抽象类中公开定义了执行它的方法的模板,它的子类可以按需重写方法实现,但调用将以抽象类中的定义方式进行 简单来说:模板方法模式定义了一个 操作中的算法的骨架
,而将一些步骤延迟到子类
中,使得子类可以不改变一个算法结构,就可以重新定义该算法的某些特定步骤模板方法模式属于行为型模式
模板方法模式类图
说明
-
AbstractClass 抽象类,类中实现了模板方法,定义了算法的骨架,具体的子类需要去实现其他的抽象方法operation2,3,4 -
ConcreteClass 实现抽象方法operation2,3,4 以完成算法中特点子类的步骤
好了接下来使用应用案例来进行理解一下吧。
豆浆制作应用实例要求
说明如下:
-
制作豆浆的流程 选材—>添加配料—>浸泡—>放到豆浆机打碎 -
通过添加不同的配料,可以制作出不同口味的豆浆 -
选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的(红豆、花生豆浆)
类图
代码演示
-
SoyaMilk(抽象类,表示豆浆)
public abstract class SoyaMilk {
//模板方法, make , 模板方法可以做成final , 不让子类去覆盖.
final void make() {
select();
addCondiments();
soak();
beat();
}
//选材料
void select() {
System.out.println("第一步:选择好的新鲜黄豆 ");
}
//添加不同的配料, 抽象方法, 子类具体实现
abstract void addCondiments();
//浸泡
void soak() {
System.out.println("第三步, 黄豆和配料开始浸泡, 需要3小时 ");
}
void beat() {
System.out.println("第四步:黄豆和配料放到豆浆机去打碎 ");
}
}
-
RedBeanSoyaMilk(红豆豆浆)
public class RedBeanSoyaMilk extends SoyaMilk {
@Override
void addCondiments() {
// TODO Auto-generated method stub
System.out.println(" 加入上好的红豆 ");
}
}
-
PeanutSoyaMilk(花生豆浆)
public class PeanutSoyaMilk extends SoyaMilk {
@Override
void addCondiments() {
// TODO Auto-generated method stub
System.out.println(" 加入上好的花生 ");
}
}
-
Client(调用)
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
//制作红豆豆浆
System.out.println("----制作红豆豆浆----");
SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk();
redBeanSoyaMilk.make();
System.out.println("----制作花生豆浆----");
SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
peanutSoyaMilk.make();
}
}
模板方法模式的钩子方法
模板方法模式的钩子方法
-
在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为“钩子”。 -
还是用上面做豆浆的例子来讲解,比如,我们还希望制作纯豆浆,不添加任何的配料,请使用钩子方法对前面的模板方法进行改造
代码演示
-
SoyaMilk
//抽象类,表示豆浆
public abstract class SoyaMilk {
//模板方法, make , 模板方法可以做成final , 不让子类去覆盖.
final void make() {
select();
if(customerWantCondiments()) {
addCondiments();
}
soak();
beat();
}
//选材料
void select() {
System.out.println("第一步:选择好的新鲜黄豆 ");
}
//添加不同的配料, 抽象方法, 子类具体实现
abstract void addCondiments();
//浸泡
void soak() {
System.out.println("第三步, 黄豆和配料开始浸泡, 需要3小时 ");
}
void beat() {
System.out.println("第四步:黄豆和配料放到豆浆机去打碎 ");
}
//钩子方法,决定是否需要添加配料
boolean customerWantCondiments() {
return true;
}
}
-
PureSoyaMilk(纯豆浆)
public class PureSoyaMilk extends SoyaMilk{
@Override
void addCondiments() {
// TODO Auto-generated method stub
//空实现
}
@Override
boolean customerWantCondiments() {
// TODO Auto-generated method stub
return false;
}
}
(红豆豆浆)和(花生豆浆)不变
-
Client
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("----制作纯豆浆----");
SoyaMilk pureSoyaMilk = new PureSoyaMilk();
pureSoyaMilk.make();
}
}
以上就是模板方法模式的基本概念以及应用案例的展示,不知道是否对模板方法模式有更好的一个理解。接下来给大家讲解一下模板方法模式在Spring源码中的应用。
模板方法模式在Spring框架应用的源码分析
Spring IOC容器初始化时运用到的模板方法模式
代码分析
-
首先我们先查看 ConfigurableApplicationContext
这个类,它里面有一个非常重要的方法Refresh
方法,这是一个抽象的方法,
-
我们看到 它有一个子类 AbstractApplicationContext
-
在 AbstractApplicationContext
这个类里面就有refresh()
方法
由此可见refresh()
就是一个模板方法
-
在 AbstractApplicationContext
这个类中的refresh()
方法中还有一个obtainFreshBeanFactory()
方法。
-
我们继续追这个 obtainFreshBeanFactory()
方法发现里面有refreshBeanFactory()
和getBeanFactory()
这两个方法,
-
我们点击 refreshBeanFactory()``getBeanFactory()
这两个方法发现它们是当前类的抽象方法(会被它的子类去实现)
-
AbstractApplicationContext 的子类 这里就不一一查看了
-
但是在子类
GenericApplicationContext
中有实现refreshBeanFactory()``getBeanFactory()
这两个方法
我们继续查看Refresh()
方法是否有钩子方法
-
然后 我们查看其中的 postProcessBeanFactory()
方法,发现这是一个“空方法`。它的意义就是让子类覆盖它,确定其就是一个钩子方法
-
onRefresh()
也是一个钩子方法
说了这么多不知是不是有点蒙呢。用图形总结一下吧:
讲到这里本章节的模板方法模式就已经讲完了。不知小伙伴是否有所收获呢。如果有欢迎点赞关注。
微信搜索【
码上遇见你
】获取更多精彩内容
原文始发于微信公众号(码上遇见你):模板模式
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/78916.html