博主声明:
转载请在开头附加本文链接及作者信息,并标记为转载。本文由博主 威威喵 原创,请多支持与指教。
本文首发于此 博主:威威喵 | 博客主页:https://blog.csdn.net/smile_running
这是23种设计模式中的模板模式(template pattern),也是最简单的设计模式之一。何为模板,就是指一种已经规定的格式,一种套路。它的作用:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
我们在大学时期不经常干的事就是拿别人的 PPT、Wrod 改一改就交上去了吗,其中改变的肯定就是将自己的姓名、学号、心得体会等替换掉,剩下的就看老师给不给过了,哈哈!
其中运用的就是模板模式,将一些规定好的格式写成模板,改变的只是自己的个人信息。然后,又来了一位同学,问你有没有不要的作业啊,然后你又将自己作业发了一份给他,他又改成了自己的信息,完美的做到了作业复用的效果,也就是我们经常说的代码复用。成功的骗过了老师,你们都得了个 D ,哈哈哈哈,额,也许这个模板不够好。
模板模式,你可能都用过,只是没有这个概念而已。一般而言,Base基类都使用了模板模式,将子类相同的操作抽离到父类中,把不同的抽象给子类实现,这就是模板模式。
虽然很简单,但还是手写一些些代码过过瘾吧。这次,我用的是英雄联盟这个游戏来做例子,这大家再熟悉不过了,游戏要打的好,代码也要敲的好!
5v5,10个玩家,打开英雄联盟客户端、登入游戏,进入排位、禁英雄、选英雄、骚操作、输了、看评分,甩锅给队友(举报),退出了游戏!多么完美的流程,我们用代码实现就是这样:
玩家 1 :
package com.xww.dp.template;public class Player1 {public Player1() {System.out.println("玩家1");}public void login() {System.out.println("登入游戏");}public void start() {System.out.println("排位");}public void ban() {System.out.println("禁用了:瞎子-盲僧");}public void select() {System.out.println("选用了:儿童劫-劫");}public void report() {System.out.println("举报:玩家2-托儿所-亚索");}public void exit() {System.out.println("退出游戏");}
}
玩家 2:
package com.xww.dp.template;public class Player2 {public Player2() {System.out.println("玩家2");}public void login() {System.out.println("登入游戏");}public void start() {System.out.println("排位");}public void ban() {System.out.println("禁用了:小学生之手-诺克萨斯之手");}public void select() {System.out.println("选用了:托儿所-亚索");}public void report() {System.out.println("举报:玩家1-儿童劫-劫");}public void exit() {System.out.println("退出游戏");}
}
其他玩家我就不写代码了,因为都一样,我们举个例子就行!然后,我们写个 Main 方法,让它们运行起来。
package com.xww.dp.template;public class TemplatePatternClient {public static void main(String[] args) {Player1 p1 = new Player1();p1.login();p1.start();p1.ban();p1.select();p1.report();p1.exit();System.out.println("--------------");Player2 p2 = new Player2();p2.login();p2.start();p2.ban();p2.select();p2.report();p2.exit();}
}
日志输出:

-
使用模板模式
我们再看看程序,这两个代码几乎一模一样,代码重复怎么办?只能考虑抽离到父类了。一套约定熟成的模板模式,其中能变化的就是禁用英雄、选英雄、举报的步骤,其它的操作每个玩家都有,也就可以抽离到父类中去,我们看看代码如何实现!
抽象基类BasePlayer 类:我们将玩家1和玩家2相同的部分抽取到 BasePlayer 基类中,将不同的部分保留下来。
package com.xww.dp.template;public abstract class BasePlayer {public void login() {System.out.println("登入游戏");}public void start() {System.out.println("排位");}protected abstract void ban();protected abstract void select();protected abstract void report();public void exit() {System.out.println("退出游戏");}}
改写玩家1类,继承 BasePlayer :
package com.xww.dp.template;public class Player1 extends BasePlayer{public Player1() {System.out.println("玩家1");}@Overrideprotected void ban() {System.out.println("禁用了:瞎子-盲僧");}@Overrideprotected void select() {System.out.println("选用了:儿童劫-劫");}@Overrideprotected void report() {System.out.println("举报:玩家2-托儿所-亚索");}
}
改写玩家2类,同样继承 BasePlayer :
package com.xww.dp.template;public class Player2 extends BasePlayer{public Player2() {System.out.println("玩家2");}@Overrideprotected void ban() {System.out.println("禁用了:小学生之手-诺克萨斯之手");}@Overrideprotected void select() {System.out.println("选用了:托儿所-亚索");}@Overrideprotected void report() {System.out.println("举报:玩家1-儿童劫-劫");}
}
Main 方法不需要改变,因为这是执行的流程,所以一般而言使用模板方法是不影响程序逻辑的,原先什么逻辑还依旧是什么逻辑,代码照样可以运行才对。我们看运行结果:

与改写前的运行结果完全一致,不影响程序的逻辑,使得代码可以得到复用,更能体现面向对象编程的思维,运用到了继承、抽象方法的编程手段。简而言之,通过这个例子,相信你会很快的掌握模板模式,并且要将这种设计模式充分的运用到自己的项目中去,那才会真正的体会到模板模式给我们带来的快乐!


















