3 优点
- 提高复用性
- 提高扩展性
- 符合开闭原则
- 封装不变部分,扩展可变部分
把认为是不变部分的算法封装到父类实现,而可变部分的则可以通过继承来继续扩展
- 提取公共部分代码,便于维护
如果我们不抽取到父类中,任由这种散乱的代码发生,想想后果是什么样子?维护人员为了修正一个缺陷,需要到处查找类似的代码 - 行为由父类控制,子类实现
基本方法由子类实现,因此子类可以通过扩展的方式增加相应的功能,符合开闭原则
4 缺点
- 类数目增加
- 增加了系统实现的复杂度
- 继承关系自身缺点,如果父类添加新的抽象方法,所有子类都要改一遍
抽象类负责声明最抽象、最一般的事物属性和方法,实现类完成具体的事物属性和方法
但是模板方法模式却颠倒了,抽象类定义了部分抽象方法,由子类实现,子类执行的结果影响了父类的结果,也就是子类对父类产生了影响,这在复杂的项目中,会带来代码阅读的难度,而且也会让新手产生不适感。
相关设计模式
模板方法模式和工厂方法模式
模板方法模式和策略模式
案例
最佳实践
初级程序员在写程序的时候经常会问高手“父类怎么调用子类的方法”。这个问题很有普遍性,反正我是被问过好几回,那么父类是否可以调用子类的方法呢?我的回答是能,但强烈地、极度地不建议这么做,那该怎么做呢?
把子类传递到父类的有参构造中,然后调用
● 使用反射的方式调用
● 父类调用子类的静态方法
这三种都是父类直接调用子类的方法,好用不?好用!解决问题了吗?解决了!项目中允许使用不?不允许!
我就一直没有搞懂为什么要用父类调用子类的方法。如果一定要调用子类,那为什么要继承它呢?搞不懂。其实这个问题可以换个角度去理解,父类建立框架,子类在重写了父类部分的方法后,再调用从父类继承的方法,产生不同的结果(而这正是模板方法模式)。这是不是也可以理解为父类调用了子类的方法呢?你修改了子类,影响了父类行为的结果,曲线救国的方式实现了父类依赖子类的场景,模板方法模式就是这种效果。
模板方法在一些开源框架中应用非常多,它提供了一个抽象类,然后开源框架写了一堆子类。
如果你需要扩展功能,可以继承这个抽象类,然后重写protected方法,再然后就是调用一个类似execute方法,就完成你的扩展开发,非常容易扩展的一种模式。
应用
主要是用来解决复用和扩展两个问题。
复用
所有子类可复用父类中模板方法定义的流程代码。
Java IO库,如InputStream、OutputStream、Reader、Writer。以InputStream为例说明。
read()是个模板方法,定义了读取数据的整个流程,并且暴露了一个可以由子类来定制的抽象方法。
不过这个方法也被命名为了read(),只是参数跟模板方法不同。
扩展
AbstractList
优点
1、封装不变部分,扩展可变部分。
2、提取公共代码,便于维护。
3、行为由父类控制,子类实现。
缺点
每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。