您的位置:首页 > 其它

设计模式之模版方法模式

2017-10-24 10:29 211 查看
目的:

1、什么是模板方法模式

2、模板方法模式如何实现

3、如何在模板方法模式中增加灵活性

4、专门行业是如何使用模板方法模式

模版方法模式:

定义了一个操作算法框架,而将一些步骤延迟到子类中实现,使得子类在不改变一个算法结构的同时就重新定义该算法的某些特定步骤,这就是模版方法

模板方法模式结构

1、定义抽象基类

1.1、实现方法(通用共同属性)

1.2、抽象方法(延迟方法)

1.3、钩子方法(扩展点)

1.4、模板方法(一定要用final因为要禁止子类对方法框架的覆写)

2、子类

模版方法采用抽象类的方式,对于固定的方法在父类中实现,而对于有差异的方法,留到子类中由子类自行实现。

开发具体步骤:用抽象基类定义框架,具体子类实现延迟步骤,钩子使子类更加灵活

创建抽象基类,为所有子类提供一个算法框架,并且在类中提供了一个常量的模版方法(即用final修饰)的抽象基类定义了算法框架而禁止子类对算法进行任何修改。

在模版类中实现基本方法,子类实现的方法设置成abstract(抽象方法)在别的类中实现。

定义一个模版类并且用这个模版类中的XXXTemple方法来定义一个框架,这个框架方法里定义了模版中方法的调用顺序,使用final关键字是为了保证不被子类改动

/*
* 抽象基类,为所有子类提供一个算法框架
*
* 提神饮料
*/
public abstract class RefreshBeverage {

/*
* 制备饮料的模板方法
* 封装了所有子类共同遵循的算法框架
*/
public final void prepareBeverageTemplate(){
// 步骤1.将水煮沸
boilWater();
// 步骤2.泡制饮料
brew();
// 步骤3.将饮料倒入杯中
pourInCup();
// 步骤4. 加入调味料
addCondiments();
}

/*
* 基本方法,将水煮沸
*/
private void boilWater() {
System.out.println("将水煮沸");
}
/*
* 抽象的基本方法,泡制饮料
*/
protected abstract void brew();
/*
* 基本方法,将饮料倒入杯中
*/
private void pourInCup() {
System.out.println("饮料倒入杯中");
}
/*
* 抽象的基本方法,加入调味料
*/
protected abstract void addCondiments();
}


重点:两个确定的方法使用private修饰,向子类隐藏。而两个需要子类重新定义的抽象方法则用protectedd修饰

模板方法的基本实现

思想

1、一份算法框架,大家共同遵守

2、 算法框架中分离出变与不变的部分

3、将变化的算法,延迟实现(交由具体的子类实现)

基本实现

1、用一个抽象基类,一个public final方法定义好算法框架

2、不变的部分,用private方法加以实现。(基本方法)

3、变化的部分,用protected abstract加以定义(抽象方法)

使用

1、面向接口编程

2、传入实际的实现子类给接口变量

3、接口变量调用框架方法

模板方法(使用抽象父类定义框架)

抽象父类,为所有子类提供一个算法框架

步骤:

1、定义一个公共的抽象父类

2、定义一个公共 final 的方法(封装所有子类都要遵循的算法框架)

3、算法框架中定义的方法子类实现相同的使用 private 修饰该方法并且实现,子类实现方法不一样的使用 protected abstact 修饰该方法并且不实现

4、让子类重写父类未实现的方法,实现各自的方法

5、在调用的实例对象采用 父类 实例名 = new 子类,在直接调用遵循的框架方法

1.coffee.java

/*

* 具体子类,提供了咖啡制备的具体实现

*/

public class Coffee extends RefreshBeverage {
@Override
protected void brew() {
System.out.println("用沸水冲泡咖啡");
}
@Override
protected void addCondiments() {
System.out.println("加入糖和牛奶");
}
}


2.tea.java

/*

* 具体子类,提供了制备茶的具体实现

*/

public class Tea extends RefreshBeverage {
@Override
protected void brew() {
System.out.println("用80度的热水浸泡茶叶5分钟");
}
@Override
protected void addCondiments() {
System.out.println("加入柠檬");
}
@Override
/*
* 子类通过覆盖的形式选择挂载钩子函数
*/
protected boolean isCustomerWantsCondiments(){
return false;
}
}


主方法体:

System.out.println("制备咖啡...");
RefreshBeverage b1 = new Coffee();
b1.prepareBeverageTemplate();
System.out.println("咖啡好了!");
System.out.println("\n******************************************");
System.out.println("制备茶...");
RefreshBeverage b2 = new Tea();
b2.prepareBeverageTemplate();
System.out.println("茶好了!");


Hook,钩子函数,提供一个默认或空的实现,具体的子类可以自行决定是否挂钩以及如何挂钩(实现函数的逻辑),询问用户是否加入调料。

钩子函数:提供一个默认的或者空的实现。

具体的子类可以自行决定是否挂钩以及如何挂钩。

也就是提供一个方法,子类想更改就更改,不更改就走默认的。

采用钩子函数来让子类自行判断要不要挂钩,在父类的实现框架中添加if语句做判断,然后再添加一个钩子函数来返回是否需要挂钩,在子类中也要重写这个方法来决定这个子类是否挂钩

钩子函数的使用,使固定的父类模版显得更加灵活,因为并不是所有子类的过程都遵循着父类的规则。而存在的这些些许的差异,因为钩子函数的引入,使得子类的过程可以
cede
和父类的过程存在变通性

用钩子(Hook)函数实现子类对算法框架个性化的扩展

1、思想

框架通过提供一个个的钩子,使框架具备了更大的灵活性。不想执行算法框架中的某些个步骤,我们可以脱钩,如果想执行的话,我们可以挂钩。

2、实现

在抽象类中,提供protected钩子方法。这是个实现的或空的方法。这样子类就可以选择覆写-持钩,也可以选择不覆写-脱勾。

3、使用

提供一个isXXX类型的钩子方法。用该方法控制算法框架中

4、某个步骤是否执行

子类不覆写这个方法,就是脱钩,仍按框架逻辑执行,一旦覆写,就是挂钩,将改变框架算法方向,按子类逻辑执行。

/*
* Hook, 钩子函数,提供一个默认或空的实现
* 具体的子类可以自行决定是否挂钩以及如何挂钩
* 询问用户是否加入调料
*/

protected boolean isCustomerWantsCondiments() {
return true;
}


模版方法模式的实现要素

准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性,最后将方法汇总构成一个不可改变的模版方法。

模版方法模式的缺点是多继承,因为抽象父类是一个class,所以如果子类由于业务需求需要继承某个类,这时由于无法多继承的原因就无法使用模版方法。(继承:由于java中的单继承不能再继承其他类)

参考视频:http://www.imooc.com/learn/145
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式 框架