模板方法模式是类的行为模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。
优点
1、封装不变部分,扩展可变部分。
2、提取公共部分代码,便于维护。
3、行为控制交由子类来实现。(开闭原则)
缺点
按照我们设计习惯,抽象类负责声明最抽象、最一般的事物属性和方法,实现类完成具体的事物属性和方法,但是模板方法模式却颠倒了,抽象类定义了部分抽象方法,由子类实现,子类执行的结果影响了父类的结果,也就是子类对父类产生了影响,这在复杂的项目中,会带来代码阅读的难度,而且也会让新手产生不适感。
适用性
1、多个子类有公有的方法,并且逻辑基本相同时。
2、重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
3、重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为。
实现
根据模板方法模式的特点,假设一个应用场景,韩梅和李雷要去参加聚会,出门前要好好的打扮一下,韩梅需要化妆挑衣服,李雷则不需要化妆挑选好衣服后,就可以出门,现在来实现。类图如下:
Human抽象类实现:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package com.lidaming.design14.template; public abstract class Human { public boolean isGirl() { return false; } public abstract void dressUp(); public abstract void chooseClothes(); public void go() { if(isGirl()) { dressUp(); } chooseClothes(); System.out.println("Ready?GO!"); } }
HanMei的实现:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package com.lidaming.design14.template; public class HanMei extends Human { @Override public boolean isGirl() { // TODO Auto-generated method stub return true; } @Override public void dressUp() { System.out.println("be a beauty"); } @Override public void chooseClothes() { System.out.println("choose a beautiful dress"); } }
LiLei的实现:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package com.lidaming.design14.template; public class LiLei extends Human { @Override public boolean isGirl() { return false; } @Override public void dressUp() { System.out.println("boy need not dress up"); } @Override public void chooseClothes() { System.out.println("choose a cool coat"); } }
场景类的实现:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package com.lidaming.design14.template; public class Client { public static void main(String[] args) { Human human = new HanMei(); human.go(); human=new LiLei(); human.go(); } }
参考:
http://www.cnblogs.com/cbf4life/archive/2010/01/05/1639487.html
http://www.cnblogs.com/java-my-life/archive/2012/05/14/2495235.html