为了账号安全,请及时绑定邮箱和手机立即绑定

java《Head First 设计模式》之模板方法模式——冲泡咖啡和茶

标签:
Java

《Head First 设计模式》之模板方法模式——冲泡咖啡和茶

模板方法模式(Template)

  • 在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

  • 好莱坞原则:别调用(打电话给)我们,我们会调用(打电话给)你。
    要点:
  • 1.模板方法的抽象类可以定义具体方法、抽象方法和钩子。抽象方法由子类实现。
  • 2.钩子是一种方法,在抽象类中不做事,或只做默认的事,子类可以选择要不要覆盖它。
  • 3.为了防止子类改变模板方法中的算法,可以将模板方法声明为final。
  • 4.好莱坞原则告诉我们,将决策权放在高层模块中,以便决定如何以及何时调用低层模块。
  • 5.策略模式和模板方法模式都封装算法,一个用组合,一个用继承。
  • 6.工厂方法(由子类决定实例化哪个具体类)是模板方法(子类决定如何实现算法中的步骤)的一种特殊版本。

示例:

咖啡冲泡法

  • 1.把水煮沸
  • 2.用沸水冲泡咖啡
  • 3.把咖啡倒进杯子
  • 4.加糖和牛奶

    茶冲泡法

  • 1.把水煮沸
  • 2.用沸水冲泡茶叶
  • 3.把茶倒进杯子
  • 4.加柠檬
    茶和咖啡是如此得相似,似乎我们应该将共同的部分抽取出来,放进一个基类中。

 1 public abstract class CaffeineBeverage {
 2     // 现在,用同一个prepareRecipe()方法来处理茶和咖啡。
 3     // prepareRecipe()方法被声明为final,因为我们不希望子类覆盖这个方法
 4     // 我们将第2步和第4步泛化成为brew()和addCondiments()
 5     final void prepareRecipe() {
 6         boilWater();
 7         brew();
 8         pourInCup();
 9         addCondiments();
10     }
11 
12     // 因为咖啡和茶处理这些方法的做法不同,所以这两个方法必须被声明为抽象,
13     // 剩余的东西留给子类去操心
14     abstract void addCondiments();
15     abstract void brew();
16 
17     public void boilWater() {
18         System.out.println("Boiling water");
19     }
20 
21     public void pourInCup() {
22         System.out.println("Pouring into cup");
23     }
24 }
  • 让我们细看抽象类是如何被定义的,包括了它内含的模板方法和原语操作。
 1 public class Coffee extends CaffeineBeverage {
 2     @Override
 3     void brew() {
 4         System.out.println("Dripping coffee through filter");
 5     }
 6 
 7     @Override
 8     void addCondiments() {
 9         System.out.println("Adding Sugar and Milk");
10     }
11 }
12 
13 public class Tea extends CaffeineBeverage {
14     @Override
15     void brew() {
16         System.out.println("Steeping the tea");
17     }
18 
19     @Override
20     void addCondiments() {
21         System.out.println("Adding Lemon");
22     }
23 }

钩子的使用

 1 public abstract class CaffeineBeverageWithHook {
 2     final void prepareRecipe() {
 3         boilWater();
 4         brew();
 5         pourInCup();
 6         // 我们加上了一个小小的条件语句,而该条件是否成立,
 7         // 是由一个具体方法customerWantsCondiments()决定的。
 8         // 如果顾客“想要”调料,只有这时我们才调用addCondiments()。
 9         if (customerWantsCondiments()) {
10             addCondiments();
11         }
12     }
13 
14     abstract void addCondiments();
15     abstract void brew();
16 
17     public void boilWater() {
18         System.out.println("Boiling water");
19     }
20 
21     public void pourInCup() {
22         System.out.println("Pouring into cup");
23     }
24 
25     // 我们在这里定义了一个方法,(通常)是空的缺省实现。这个方法只会返回true,不做别的事。
26     // 这就是一个钩子,子类可以覆盖这个方法,但不见得一定要这么做。
27     boolean customerWantsCondiments() {
28         return true;
29     }
30 }
复制代码

用模板方法排序

  Java数组类的设计者提供给我们一个方便的模板方法用来排序。必须实现Comparable接口,提供这个接口所声明的compareTo()方法。

其他模板方法实例

  • 1.java.io的InputStream类有一个read()方法,是由子类实现的,而这个方法又会被read(byte b[], int off, int len)模板方法使用。
  • 2.Swing的JFrame继承了一个paint()方法。在默认状态下,paint()是不做事情的,因为它是一个“钩子”。通过覆盖paint(),可以将自己的代码插入JFrame的算法中,显示出想要的画面。
  • 3.applet是一个能在网页上面执行的小程序。任何applet必须继承自Applet类,而Applet类中提供了好些钩子。

  • www.cnblogs.com/-1307/p/6441182.html
点击查看更多内容
3人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
37
获赞与收藏
165

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消