模板方法设计模式
来源:互联网 发布:java购物商城源码 编辑:程序博客网 时间:2024/06/06 01:23
概览
概述
准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性。最后将方法汇总成一个不可改变的模板方法。
如何实现
第一步
- 提供抽象基类;
- 在基类中提供一个final(final是为了防止算法逻辑被重写修改)的模板算法框架,这个算法框架所有子类必须共同遵循;
- 基本方法在基类中实现,使用private权限修饰,向下层隐藏细节;
- 提供抽象方法,延续到子类中实现;
- 可选的钩子方法,具体的子类决定是否挂钩以及如何挂钩。
第二步
- 实现基类中的抽象方法,完成个性化实现;
- 覆盖基类中的钩子方法(可选)。
特点
优点
- 封装性好;
- 复用性好;
- 屏蔽细节;
- 便于维护。
缺点
- Java中的单继承问题
应用场景
- 算法或者操作遵循相同罗逻辑;
- 重构时(相同代码抽取到一个基类中);
- 重要,复杂的算法以及核心算法的设计。
分析一个坐火车的情形
- 买票
- 去火车站
- 上车
- 目的地下车
如果要坐火车,这四步就是基本的流程,但是买票我可以有多种选择,可以去窗口买,可以在12306客户端买,这个细节根据每个人的习惯而不一样,所以基类不帮你实现,要定义一个抽象方法延续到子类中去实现,还有下车的目的地也不尽相同。但是其它两步都是确定的,这就可以在基类中实现。
代码实现
上基类的代码及注释:
/*** 乘坐火车的模板方法设计模式的基类*/public abstract class ByTrainTemplate {public final void byTrainTemplateMethod() { buyTicket(); goToRailWayStation(); getOnTrain(); detrain();}/** * 买票的方式不确定,延续到子类中去实现 */protected abstract void buyTicket();/** * 都要去火车站乘车的,所以在基类中就可以实现 * 用private屏蔽细节 */private void goToRailWayStation() { Log.e("template","去火车站");}protected void getOnTrain(){ Log.e("template","上车");}/** * 每个人目的地不同,所以基类不实现,交由子类去实现 */protected abstract void detrain();}
乘客A的坐车过程
/*** PassengersA的乘车方法*/public class PassengersA extends ByTrainTemplate {@Overrideprotected void buyTicket() { Log.e("template","通过12306买的票");}@Overrideprotected void detrain() { Log.e("template","去兰州旅游,在兰州下车");}}
乘客B的乘车过程
/*** PassengersB的乘车旅程*/public class PassengersB extends ByTrainTemplate {@Overrideprotected void buyTicket() { Log.e("template","我在窗口买的票");}@Overrideprotected void detrain() { Log.e("template","我要去青海看青海湖,我在青海下车");}}
调用一下试试看
ByTrainTemplate passengersA = new PassengersA(); passengersA.byTrainTemplateMethod(); Log.e("template","-------------------------------------"); ByTrainTemplate passengersB = new PassengersB(); passengersB.byTrainTemplateMethod();
执行结果
E/template: 通过12306买的票 E/template: 去火车站 E/template: 上车 E/template: 去兰州旅游,在兰州下车 E/template: ------------------------------------- E/template: 我在窗口买的票 E/template: 去火车站 E/template: 上车 E/template: 我要去青海看青海湖,我在青海下车
是不是实现了结果,又很完美的避免了重复代码。这个时候铁路家属不乐意了,根据政策自己是可以免费乘车的,根本不需要买票好不好,那怎么办?这个时候就用到hook也就是所谓的钩子方法了。
改造基类,增加了一个钩子:
/** * 乘坐火车的模板方法设计模式的基类 */public abstract class ByTrainTemplate { public final void byTrainTemplateMethod() { if (isNeedTicket()) { buyTicket(); } goToRailWayStation(); getOnTrain(); detrain(); } /** * 是否需要车票才能乘车 * 大部分是需要车票的,所以默认就给个true好了 * @return */ protected boolean isNeedTicket() { return true; } /** * 买票的方式不确定,延续到子类中去实现 */ protected abstract void buyTicket(); /** * 都要去火车站乘车的,所以在基类中就可以实现 * 用private屏蔽细节 */ private void goToRailWayStation() { Log.e("template", "去火车站"); } protected void getOnTrain() { Log.e("template", "上车"); } /** * 每个人目的地不同,所以基类不实现,交由子类去实现 */ protected abstract void detrain();}
乘客C的乘车过程
/** * PassengersC的乘车过程 */public class PassengersC extends ByTrainTemplate { @Override protected void buyTicket() { Log.e("template","我是铁路职工家属,不要票"); } @Override /** * 覆盖钩子方法 */ protected boolean isNeedTicket() { return false; } @Override protected void detrain() { Log.e("template","我在西安下车"); }}
调用乘客C的乘车过程方法
ByTrainTemplate passengersC = new PassengersC();passengersC.byTrainTemplateMethod();
看结果是不是不需要买票了
E/template: 通过12306买的票E/template: 去火车站E/template: 上车E/template: 去兰州旅游,在兰州下车E/template: -------------------------------------E/template: 我在窗口买的票E/template: 去火车站E/template: 上车E/template: 我要去青海看青海湖,我在青海下车E/template: -------------------------------------E/template: 去火车站E/template: 上车E/template: 我在西安下车
其实这种方法在Android开发中我们经常用到,比如抽取出一个BaseActivity和BaseFragment等等。
阅读全文
0 0
- 模板方法设计模式
- 模板方法设计模式
- 模板方法设计模式
- 模板方法设计模式
- 【设计模式】模板方法
- 模板方法设计模式
- 设计模式--模板方法
- 模板方法设计模式
- 设计模式-模板方法
- 设计模式-模板方法
- 模板方法设计模式
- 模板方法设计模式
- 模板方法设计模式
- 模板方法设计模式
- 模板方法设计模式
- 模板方法设计模式
- 设计模式-模板方法
- 模板方法设计模式
- 倒计时日时分秒的完美实现。
- JAVA之数据库(四)
- 算法博弈:机制设计
- 【计算机网络】网络诊断工具ping的模拟实现之搭建框架
- poj3252(数位dp)
- 模板方法设计模式
- [leetcode]565. Array Nesting
- Leetcode 124. Binary Tree Maximum Path Sum
- 常用类
- anaconda 下多版本Python 安装说明
- 个人不熟悉的面试题目(c++,数据结构)
- 剑指offer--面试题28:对称的二叉树
- 实习遇到的坑....
- hdu 3549 isap