设计模式【13】-- 模板模式怎么弄?

设计模式

开局还是那种图,各位客官往下看...

张无忌学太极拳,忘记了所有招式,打倒了"玄冥二老",所谓"心中无招"。设计模式可谓招数,如果先学通了各种模式,又忘掉了所有模式而随心所欲,可谓OO之最高境界。

模板模式是什么?

模板模式,同样是一种行为型模式,也就是关于对象做什么或者怎么做设计模式。模板模式的本质需要定义操作中的算法的框架,但是有一些步骤,又不需要具体的实现,而是不同的子类各自实现。子类不能修改流程框架,但是部分的步骤可以做定制化的实现。

主要要解决一个问题:一些通用的方法,但是每一个子类却都重新写,冗余。

比如说,做菜的步骤一般是:洗锅 --> 炒菜 --> 洗碗 ,不同的菜,只是炒菜这一个步骤具体细节是不同的,但是其他步骤确实几乎一模一样的,这样其实整体框架,以及重复的步骤,我们可以抽象到模板中,而不同的细节方法可以开放给每一种菜(具体实现)去定制。

又比如造房子的时候,很多地方的建造都是一样的:地基,墙壁,水管等等,但是不同的房子里面的内部的设计又有所不同。

不使用模板模式

就挑个简单的例子“炒菜”,如果不使用模板模式的话,糖醋鲤鱼:

public class SweetAndSourCarp { public void cookFood(){ washPan(); cook(); eat(); washDishes(); System.out.println(""); } private void washPan(){ System.out.print("洗锅 --> "); } private void cook(){ System.out.print("煮糖醋鲤鱼 --> "); } private void eat(){ System.out.print("吃饭 --> "); } private void washDishes(){ System.out.print("洗碗 --> "); } }

再弄一个农家小炒肉,需要写很多相同的方法:

public class ShreddedPorkWithVegetables { public void cookFood(){ washPan(); cook(); eat(); washDishes(); System.out.println(""); } private void washPan(){ System.out.print("洗锅 --> "); } private void cook(){ System.out.print("炒农家小炒肉 --> "); } private void eat(){ System.out.print("吃饭 --> "); } private void washDishes(){ System.out.print("洗碗 --> "); } }

测试类如下:

public class Test { public static void main(String[] args) { SweetAndSourCarp sweetAndSourCarp = new SweetAndSourCarp(); sweetAndSourCarp.cookFood(); ShreddedPorkWithVegetables shreddedPorkWithVegetables = new ShreddedPorkWithVegetables(); shreddedPorkWithVegetables.cookFood(); } }

测试结果:

洗锅 --> 煮糖醋鲤鱼 --> 吃饭 --> 洗碗 --> 洗锅 --> 炒农家小炒肉 --> 吃饭 --> 洗碗 -->

可以看到,整体流程是一样的,有些步骤一样,有些步骤不一样,但是不使用模板模式,需要每个类都重写一遍方法,即使是通用方法,整个流程都需要自己写一遍。

使用模板模式优化

如果使用模板模式,那么我们会抽象出一个抽象类,定义整体的流程,已经固定的步骤,开放需要定制的方法,让具体的实现类按照自己的需求来定制。

设计模式【13】-- 模板模式怎么弄?

定义的抽象类:

public abstract class CookFood { public final void cookFood() { washPan(); cook(); eat(); washDishes(); System.out.println(""); } private final void washPan() { System.out.print("洗锅 --> "); } public abstract void cook(); private final void eat() { System.out.print("吃饭 --> "); } private final void washDishes() { System.out.print("洗碗 --> "); } }

具体的实现类糖醋鲤鱼:

public class SweetAndSourCarp extends CookFood { @Override public void cook() { System.out.print("煮糖醋鲤鱼 --> "); } }

农家小炒肉:

public class ShreddedPorkWithVegetables extends CookFood { @Override public void cook() { System.out.print("炒农家小炒肉 --> "); } }

测试类与前面的一样,测试结果也一样,这里不再重复。

上面的方法中,其实我们只开放了cook()方法,这就是钩子方法

在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为 ”钩子方法”

钩子方法是开放的,可以由子类随意覆盖,但是像上面的其他方法,我们不希望子类重写或者覆盖它,就可以用 final 关键字,防止子类重写模板方法。

模板模式的应用

其实在 JDK 的 Thread 实现中,就是使用了模板模式,我们知道创建线程有两个方式:

创建 Thread 类

实现 runnable 接口

我们实现的一般是 run() 方法, 但是调用的却是 start() 方法来启动线程,这个原因就是 start() 方法里面帮我们调用了run() 方法, run()方法是开发的方法,我们可以覆盖重写它。

设计模式【13】-- 模板模式怎么弄?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzdswd.html