模板方法模式
来源:互联网 发布:如何在淘宝上找店铺 编辑:程序博客网 时间:2024/05/15 06:27
定义&示例
HeadFirst定义:在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
其实就是将一些算法、业务步骤封装到一个方法中,使用者直接调用该模板方法,这样保证该步骤不会出错,减轻调用方压力。
老规矩先放一个demo github传送门
demo我假设了我们常用的12306买火车票场景。
把下单支付环节抽象为一个模板方法。
交易抽象类,也是模板方法所在的基类
/** * 模板基类 * * @author yasin * */public abstract class Trade { /** * 交易模板方法 * 1.冻结该票 * 2.进行支付 * 3.支付成功->出票 * 4.解冻 * * @author yasin * @param name */ public void order(String name){ frozen(name); if(pay()){ deliver(name); } unfrozen(name); } /** * 冻结该票 * * @author yasin * @param name */ private void frozen(String name){ System.out.println(name+" 已经被冻结"); } /** * 支付,抽象方法,交由具体的实体类实现 * @author yasin * @return */ protected abstract boolean pay(); /** * 解冻 * * @author yasin * @param name */ private void unfrozen(String name){ System.out.println(name+" 已经被解冻"); } /** * 出票 * @author yasin * @param name */ private void deliver(String name){ System.out.println(name +" 已经出票"); } }
像冻结,解冻,出票这些实现都是固定的,就在基本中实现了。但支付环节可以使用不同的支付方式,不同的支付方式又会调用不同的sdk,执行不同的方法。
所有我将pay()方法交由Trade的子类实现。
这里设计了ZhiFuBaoPay和CardPay两个子类,其pay方法通过调用不同的api实现自己的支付环节(由于本文的侧重点不在这,就省略没写)
public class ZhiFuBaoPay extends Trade { /** * 其实这里也是一个模板方法 * 1.获取支付账号 * 2.扣除该账号金额 * 3.为对方加入对应金额 * * 这里就省略了,默认实现是支付成功,返回了true */ @Override public boolean pay() { System.out.println("使用了 支付宝 支付了金额"); return true; }}
下面就是一个买家下单买票,代码中只需要选择支付方式(实例化对应的类),调用一个trade方法就能实现复杂的支付下单环节了,保证每个步骤都存在,不会因为实现的子类而漏掉一个方式,也节省了代码量。
public class Buyer { @Test public void main(){ //车票路段 String name = "北京到济宁"; //使用支付宝进行交易// Trade pay = new ZhiFuBaoPay();// pay.order(name); //使用银行卡进行交易 Trade cardPay = new CardPay(); cardPay.order(name); }}
这里的pay()方法还是一个钩子,通过其返回值,可以对模板方法的流程进行控制。
好莱坞原则 这里就引出了一个好莱坞原则:别调用我们,我们会调用你。
好莱坞原则是为了防止“依赖腐败”的实现发生,一个高层组件和底层组件相互依赖,高层组件依赖边层组件,边层组件又依赖底层组件,这样的依赖关系真的很乱,这就是依赖腐败问题。
当高层组件和底层组件必须依赖,那就得约定让一方只调用一方,避免相互调用。就像pay方法由底层实现,高层调用,底层不会调用高层的任何方法,保证代码的可读性。
java api的使用
模板方法是一个易于理解使用,但确实很实用的模式,java api中组数的排序也是应用这个设计思想,虽然它不是完全符合模板方法的。
java Arrays#sort方法
public static <T> void sort(T[] a, Comparator<? super T> c) { if (c == null) { sort(a); } else { if (LegacyMergeSort.userRequested) legacyMergeSort(a, c); else TimSort.sort(a, 0, a.length, c, null, 0, 0); } }
这里的Comparator是用于比较的,因为Arrays是想比较任何对象的,但开发者自己定义的类的比较方式是不确定的,这里就将比较方法暴露出来,交于其具体实现,
开发者只需要让其类实现Comparable接口,实现其比较大小的方法就可以对其对象数据进行排序了。具体的排序方法就是模板方法了,开发者完全不需要关心。
- 深入浅出模板方法模式
- 模板方法模式
- 模板方法模式
- 模板方法模式
- 模板方法设计模式
- 模板方法模式
- 模板方法模式
- 模板方法模式
- 模板方法模式
- 模板方法模式
- 模板方法模式
- 模板方法模式
- 模板方法模式
- 模板方法模式
- TemplateMethod模板方法模式
- 模板方法模式
- 模板方法模式
- 模板方法模式
- 网页编程--JavaScript之二级联动菜单设计
- maven 学习(1)
- zookeeper使用
- Go语言执行系统命令
- bzoj1093 最大半连通子图
- 模板方法模式
- 二叉树的查找删除
- sqlServer删除发布问题
- 深度学习学习笔记
- Leetcode c语言-Valid Parentheses
- 设计模式-----复杂模式
- 解决使用Git Bash乱码问题
- 《C和指针》读书笔记(一)
- 好朋友的工具合集