快捷搜索:
来自 计算机编程 2019-10-06 10:39 的文章
当前位置: 67677新澳门手机版 > 计算机编程 > 正文

【67677新澳门手机版】实现模板方法情势,冲泡咖

捋一遍全部流程

  1. 本人索要做二个茶:

67677新澳门手机版 1

  1. 下一场调用茶的模板方法:

67677新澳门手机版 2

  1. 在模板方法里面实行下列工序:

boildWater();

brew();

pourInCup();

addCondiments();

 

其余钩子例子

java的JFrame:

67677新澳门手机版 3

JFrame父类里面有三个update()方法, 它决定着算法, 大家得以采纳paint()方法来钩子进到该算法的那部分.

父类里面JFrame的paint()啥也没做, 正是个钩, 大家得以在子类里面重写paint(), 上边例子的效率就是:

67677新澳门手机版 4

 

另二个事例Applet小程序:

 67677新澳门手机版 5

那5个点子全部都是重写的钩子...

自家没看过winform大概wpf/sl的源码, 小编臆度也理应有一部分钩子吧.

钩子的应用

 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()方法。

再精激情考应该怎么设计

67677新澳门手机版 6

能够发掘四个果汁的制作方法服从了扳平的算法:

  1. 把水烧开
  2. 用热水冲咖啡或茶
  3. 把冲开的果汁放到杯里
  4. 加上适当的调料

于今我们来抽像prepareRecipe()方法:

1.先看看多个果汁的差异:

67677新澳门手机版 7

三种饮料皆有四道工序, 三个是全然一样的, 别的五个在切切实实的落实上是略有分裂的, 但是要么长久以来性质的工序.

这两道不等的工序的精神正是冲饮品和丰裕调味剂, 所以prepareRecipe()能够这么写:

67677新澳门手机版 8

  1. 把地点的格局放到超类里:

67677新澳门手机版 9

以此父类是空虚的, prepareRecipe()将会用来营造咖啡大概茶, 而且作者不想让子类去重写这么些措施, 因为制作工序(算法)是大势所趋的.

只但是里面包车型大巴第2部和第4部是索要子类本人来贯彻的. 所以brew()和addCondiments()是八个抽象的法子, 而别的多个措施则一向在父类里面完成了.

  1. 终极茶和咖啡正是那几个样子的:

67677新澳门手机版 10

 

67677新澳门手机版 11

 

任何难点

好莱坞原则和依赖反转原则DIP的的分化?

DIP告诉我们毫不使用具体的类, 尽量采纳抽象类. 而好莱坞原则则是让低端别组件能够被钩进算法中去, 也从不创建低档别组件和高档别组件间的正视性关系.

三种形式相比较:

模板方法形式: 子类决定如何完结算法中一定的手续

政策方式: 封装变化的一举一动并动用委托来决定哪些行为被使用.

厂子方法形式: 子类决定实例化哪个具体的类.

任何模板方法实例

  1. java.io的InputStream类有三个read()方法,是由子类实现的,而以此格局又会被read(byte b[], int off, int len)模板方法应用。
  2. Swing的JFrame承接了贰个paint()方法。在私下认可状态下,paint()是不做业务的,因为它是一个“钩子”。通过覆盖paint(),能够将本身的代码插入JFrame的算法中,突显出想要的镜头。
  3. applet是三个能在网页上边推行的小程序。任何applet必需承袭自Applet类,而Applet类中提供了好些个钩子。

 

好莱坞原则和模板方法情势

67677新澳门手机版 12

模板方法里, 父类调控算法, 并在要求的时候调用子类的方法.

而子类平昔不会一贯主动调用父类的方法.

 


选取模板方法做排序

拜访java里面数组的排序方法:

67677新澳门手机版 13

67677新澳门手机版 14

mergeSort就可以看做事模板方法, compareTo()便是亟需现实落到实处的方法.

可是那一个并不曾动用子类, 然则依附真实意况, 依然得以灵活采纳的, 你须求做的正是促成Comparable接口就可以., 这一个接口里面只有三个CompareTo()方法.

切实使用C#正是这么:

鸭子:

using System;

namespace TemplateMethodPattern.ForArraySort
{
    public class Duck : IComparable
    {
        private readonly string _name;
        private readonly int _weight;

        public Duck(string name, int weight)
        {
            _name = name;
            _weight = weight;
        }

        public override string ToString()
        {
            return $"{_name} weights {_weight}";
        }

        public int CompareTo(object obj)
        {
            if (obj is Duck otherDuck)
            {
                if (_weight < otherDuck._weight)
                {
                    return -1;
                }
                if (_weight == otherDuck._weight)
                {
                    return 0;
                }
            }
            return 1;
        }
    }
}

正如鸭子:

        static void SortDuck()
        {
            var ducks = new Duck[]
            {
                new Duck("Duffy", 8),
                new Duck("Dewey",  2),
                new Duck("Howard", 7),
                new Duck("Louie", 2),
                new Duck("Donal", 10),
                new Duck("Huey", 3)
            };
            Console.WriteLine("Before sorting:");
            DisplayDucks(ducks);

            Array.Sort(ducks);

            Console.WriteLine();
            Console.WriteLine("After sorting:");
            DisplayDucks(ducks);
        }

        private static void DisplayDucks(Duck[] ducks)
        {
            foreach (Duck t in ducks)
            {
                Console.WriteLine(t);
            }
        }

效果:

67677新澳门手机版 15

茶冲泡法

  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 // 这就是我们的抽象类。它被声明为抽象,用来作为基类,其子类必须实现其操作
 2 public abstract class AbstractClass {
 3     // 这就是模板方法。它被声明为final,以免子类改变这个算法的顺序。
 4     final void templateMethod() {
 5         // 模板方法定义了一连串的步骤,每个步骤由一个方法代表
 6         primitiveOperation1();
 7         primitiveOperation2();
 8         concreteOperation();
 9     }
10 
11     // 在这个范例中有两个原语操作,具体子类必须实现它们
12     abstract void primitiveOperation1();
13     abstract void primitiveOperation2();
14     
15     // 这个抽象类有一个具体的操作。
16     void concreteOperation() {
17         // ...
18     }
19 }

 

随之须求管理咖啡和茶类,这三个类未来都是借助超类来管理冲泡法,所以只须求自行管理冲泡和增进调味剂部分:

 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 }

笔者们做了怎么?

大家发掘到二种饮料的工序大假使一模二样的, 固然一些工序要求区别的落到实处方法. 所以大家把那些果汁的制作方法归咎到了贰个基类CaffeineBeverage里面.

CaffeineBeverage调节着漫天工序, 第1, 3部由它和谐完结, 第2, 4步则是由具体的果汁子类来完结.

模板方法方式(Template)

  ——在贰个方法中定义了一个算法的骨架,而将有个别手续延迟到子类中。模板方法使得子类能够在不转移算法结构的意况下,重新定义算法中的某个步骤。

  • 好莱坞原则:别调用(打电话给)大家,大家会调用(打电话给)你。
  • 要点:
  1. 模板方法的抽象类能够定义具体方法、抽象方法和钩子。抽象方法由子类完毕。
  2. 钩子是一种形式,在抽象类中不坐班,或只做暗许的事,子类能够接纳要不要覆盖它。
  3. 为了防御子类改动模板方法中的算法,能够将模板方法注解为final。
  4. 好莱坞原则告诉我们,将发言权放在高层模块中,以便调整怎么着以及曾几何时调用低层模块。
  5. 政策格局和模板方法方式都打包算法,一个用结合,二个用持续。
  6. 厂子方法(由子类决定实例化哪个具体类)是模板方法(子类决定哪些兑现算法中的步骤)的一种相当版本。

 

示例:

模板方法定义

模板方法在两个措施里定义了一套算法的骨子, 算法的一些步骤能够让子类来促成. 模板方法让子类重新定义算法的少数步骤而无需改变算法的结构.

类图:

67677新澳门手机版 16

本条抽象类:

67677新澳门手机版 17

本着这一个抽象类, 大家得以有局部扩大:

67677新澳门手机版 18

看这几个hook方法, 它是三个具体的措施, 然而吗也没做, 这种就称为钩子方法. 子类能够重写该形式, 也能够不重写.

咖啡冲泡法

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

模板方法有何利益?

不采用模板方法时:

  • 咖啡和茶各自笔者调节制自身的算法.
  • 果汁间的代码重复.
  • 改动算法要求修改八个地点
  • 加多新果汁供给做过多事业.
  • 算法遍及在了分化的类里面

行使模板方法后:

  • CaffeineBeverage这几个父类调节并爱抚算法
  • 父类最大化的代码的复用
  • 算法只在贰个地点, 改造算法也只需更动那么些地点
  • 新的果汁只需兑现部分工序就能够
  • 父类驾驭着算法, 可是借助子类去做具体的达成.

本文由67677新澳门手机版发布于计算机编程,转载请注明出处:【67677新澳门手机版】实现模板方法情势,冲泡咖

关键词: