模板方法模式学习笔记

模板方法的实现要素:抽象基类和具体子类。

抽象基类:(1)基本方法:共有的方法,用private修饰

     (2)抽象方法:只知道原则,不知道具体实现,要延迟到子类中实现,用protected abstract修饰

       (3)可选的钩子:具体的子类可以自行决定是否挂钩以及如何挂钩,从而影响算法的实现,用protected修饰

       (4)Template方法:封装了所有子类共同遵循的算法框架,用final修饰,不让子类覆盖重写。

                 模板方法定义成final,即表示子类可以替换掉父类中的可变逻辑,但不能改变掉整体逻辑结构。(好莱坞原则)

具体子类:(1)实现基类中的抽象方法

       (2)可选的覆盖钩子方法,来更加个性化来影响算法的局部行为。

总结:

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

模板方法模式的适用场景:

(1)算法或操作遵循相似的逻辑

(2)重构时(把相同的代码抽取到父类中)

(3)重要,复杂的算法,核心算法设计为模板算法

模板方法模式的优点:

(1)封装性好

(2)复用性好

(3)屏蔽细节

(4)便于维护

模板方法模式的缺点:

(1)继承(Java语言只支持单继承),但我们重构一个系统时,假如有些类已经继承了相关父类,那就无法再继承模板方法的抽象基类。

简单代码示例如下:

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

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

if(isCustomerWantsCondiments()) {
// 步骤4:加入调味料
addCondiments();
}

}

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

/*
* 基本方法,将水煮沸
*/
private void boilWater() {
System.out.println("将水煮沸");
}

/*
* 抽象的基本方法,泡制饮料
*/
protected abstract void brew();

/*
* 基本方法,将饮料倒入杯中
*/
private void pourInCup() {
System.out.println("将饮料倒入杯中");
}

/*
* 抽象的基本方法:加入调味料
*/
protected abstract void addCondiments();

}

/**
* 具体子类,提供了制备咖啡的具体实现
* @author zhx
*
*/
public class Coffee extends RefreshBeverage {

@Override
protected void brew() {
System.out.println("用沸水冲泡咖啡");
}

@Override
protected void addCondiments() {
System.out.println("加入糖和牛奶");
}

}

/**
* 具体子类:提供了制备茶的具体实现
* @author zhx
*
*/
public class Tea extends RefreshBeverage{

@Override
protected void brew() {
System.out.println("用80℃的热水浸泡茶叶5分钟");
}

@Override
protected void addCondiments() {
System.out.println("加入柠檬");
}

/*
* 子类通过覆盖的形式选择挂载钩子函数
* @see edu.bnuz.zhx.design_pattern.template.RefreshBeverage#isCustomerWantsCondiments()
*/
@Override
protected boolean isCustomerWantsCondiments() {
return false;
}

}

public class RefreshBeverageTest {

public static void main(String[] args) {

System.out.println("制备咖啡中...");
RefreshBeverage coffee = new Coffee();
coffee.prepareBeverageTemplate();
System.out.println("咖啡制备完成...");

System.out.println("-----------------------------------");
System.out.println("制备茶中...");
RefreshBeverage tea = new Tea();
tea.prepareBeverageTemplate();
System.out.println("茶制备完成...");
}

}

时间: 2024-09-30 18:31:12

模板方法模式学习笔记的相关文章

WPF-MVVM模式学习笔记3——MVVM概念再次挖掘

通过上篇文章<WPF-MVVM模式学习笔记2--MVVM简单样例>中举了一个例子,我对MVVM大概有了一个比较浅显的意思.同时,看过前两篇文章的人,也知道我的这个系列的文章大多数来源于其他的博客,我其实只是起了一个汇总的作用,毕竟我也是在学习,肯定是要去网络上学习别人的笔记喽.本篇文章将以温故而知新的方式再次去理解MVVM,力求对MVVM的认识再深一个层次. 1.再看"M-V-VM" M:即Model,由现实世界抽象出来的模型. V:即View,视图,界面,该界面与用户输入

大端模式 && 小端模式学习笔记

Big-Endian和Little-Endian的定义如下:1) Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端.2) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端. 不同字节序如何存储数据? 看看两种方式如何存储数据,假设从地址0x00000001处开始存储十六进制数0x12345678,那么 Bit-endian 如此存放(按原来顺序存储)0x00000001           -- 120x00000002 

策略模式学习笔记

策略模式定义:将可变的部分从程序中抽象分离成算法接口,在该接口下分别封装一系列算法实现,并使它们可以相互替换,从而导致客户端程序独立于算法的改变. 策略模式区别于模板方法模式: - 策略模式强调整体算法,即将整个算法交由用户实现.(采用组合方式) - 模板方法模式强调部分算法,即整体算法不变情况下,部分子算法实现交由用户实现.(采用继承方式) 设计原则: - 找出不变部分抽象成接口(鸭子鸣叫行为),找出变化部分使用具体实现.(鸭子不叫,鸭子嘎嘎叫,鸭子唧唧叫) - 面向接口编程,而不是面向实现编

[GeekBand] 设计模式——工厂模式学习笔记

 本文参考文献:GeekBand课堂内容,授课老师:李建忠 :大话设计模式 其余的模式方法请自行查看Geekband相关课程,在此不累述. 这周的课题是: 针对DrawingSystem中的基类Shape和各个子类Line.Rec.Circle.为支持更多的形状子类,请使用某种模式来支持灵活地创建它们.使用松耦合面向对象设计方法和思想,可使用伪码表示设计. 课程中提到了四种模式,“工厂方法”.“抽象工厂”.“原型模式”.“构建器”模式.最后聚焦在了“工厂方法”和“抽象工厂”这两种方法,那么第一个

面向对象编程中设计模式学习笔记

上学期学的OOP,最近把期末复习笔记拿出来温习,共享一发. Polymorphism means many different form If you have inheritance, you have polymorphism Inheritance Polymorphism Abstraction Encapsulation Information hiding Loose coupling Hello.exe (an executable) Hello.dll (an assembly

SQL反模式学习笔记11 限定列的有效值

2014-10-14 08:46:07 目标:限定列的有效值,将一列的有效字段值约束在一个固定的集合中.类似于数据字典. 反模式:在列定义上指定可选值 1. 对某一列定义一个检查约束项,这个约束不允许往列中插入或者更新任何会导致约束失败的值:            create table Bugs(status varchar(20) check(status in('new','in progress','fixed'))). 2.使用域或者用户自定义类型(UDT)等方法.        

SQL反模式学习笔记6 支持可变属性【实体-属性-值】

2014-10-11 17:21:31 目标:支持可变属性 反模式:使用泛型属性表.这种设计成为实体-属性-值(EAV),也可叫做开放架构.名-值对. 优点:通过增加一张额外的表,可以有以下好处 (1)表中的列很少: (2)新增属性时,不需要新增列.不会影响现有表的结构: (3)存储的字段内容不会为空值. 缺点:(1)查询语句变得更加复杂: (2)使用EAV设计后,需要放弃传统的数据库设计所带来的方便之处,比如:无法保障数据完整性: (3)无法使用SQL的数据类型,比如对日期.金钱等格式内容都只

SQL反模式学习笔记3 单纯的树

2014-10-11 08:59:48 在树形结构中,实例被称为节点.每个节点都有多个子节点与一个父节点. 最上层的节点叫做根(root)节点,它没有父节点. 最底层的没有子节点的节点叫做叶(leaf). 中间的节点简单地称为非叶节点(nonleaf). 目标:分成存储于查询,比如:系统字典.组织机构.省份区域等树形结构数据或者以层级方式组织的数据. 反模式:总是依赖父节点,邻接表. 最简单的实现方式是添加ParentId字段,引用同一张表的主键ID. 邻接表维护树比较方便,但是查询很笨拙,如果

SQL反模式学习笔记7 多态关联

2014-10-13 09:50:54 目标:引用多个父表 反模式:使用多用途外键.这种设计也叫做多态关联,或者杂乱关联. 多态关联和EAV有着相似的特征:元数据对象的名字是存储在字符串中的. 在多态关联中,父表的名字是存储在Issue_Type单独一列中,有时候这样的设计被称作:混合数据与原数据. 查询示例: select * from A as a               left join B as b on a.xId=b.Id and a.xType='b'