设计模式之----模板模式

设计模式之模板模式

  • 模板模式总结
  • 泡茶和泡咖啡的案例
  • 传统设计
  • 模板方法设计
  • Sort排序算法应用模板方法设计模式
  • 好莱坞原则

模板模式总结

这里写图片描述
这里写图片描述

  • 封装了一个算法步骤,并允许子类为一个或多个步骤方法提供实现,模板模式可以使得子类在不改变算法结构的情况下,重新定义算法中的某些实现;
  • 在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行;
  • 应用: 1、在造房子的时候,地基、走线、水管都一样,只有在建筑的后期才有加壁橱加栅栏等差异。 2、西游记里面菩萨定好的 81 难,这就是一个顶层的逻辑骨架。 3、spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来,比如开启事务、获取 Session、关闭 Session 等,程序员不重复写那些已经规范好的代码,直接丢一个实体就可以保存。
  • 优点:1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
  • 使用场景 : 1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。
  • 一般模板方法都加上 final 关键词。

泡茶和泡咖啡的案例

这里写图片描述

传统设计

这里写图片描述

package templateMethod.bad;
/**
 * 泡咖啡的
 */
public class Coffee {
    //步骤
    public void prepareRecipe(){
        boilWater();
        brewCoffee();
        pourInCup();
        addSugarMilk();
    }

    public void boilWater(){
        System.out.println("Boiling Water!");
    }
    public void brewCoffee(){
        System.out.println("Brewing Coffee!");
    }
    public void pourInCup(){
        System.out.println("Pouring into cup!");
    }
    public void addSugarMilk(){
        System.out.println("Adding sugar and milk!");
    }
}
package templateMethod.bad;
/**
 * 泡热饮
 */
public class Tea {

    public void prepareRecipe(){
        boilWater();
        brewTea();
        pourInCup();
        addLemon();
    }
    public void boilWater(){
        System.out.println("Boiling Water!");
    }
    public void brewTea(){
        System.out.println("Brewing Tea!");
    }
    public void pourInCup(){
        System.out.println("Pouring into Cup!");
    }
    public void addLemon(){
        System.out.println("Adding Lemon!");
    }
}
package templateMethod.bad;
public class MyTest {
    public static void main(String[] args) {

        Coffee coffee = new Coffee();
        Tea tes = new Tea();

        coffee.prepareRecipe();
        System.out.println("------------------");
        tes.prepareRecipe();
    }
}

模板方法设计

这里写图片描述
这里写图片描述

代码:

package templateMethod.good;

public abstract class HotDrink {

    //模板方法
    public final void prepareRecipe(){
        boilWater();
        brew();
        pourInCup();

        if(wantCondimentsHook()){
            addCondiments();
        }else{
            System.out.println("No Condiments!");
        }
    }

    //最终方法  不能修改的
    public final void boilWater(){
        System.out.println("Boiling Water!");
    }
    public final void pourInCup(){
        System.out.println("Pouring into cup!");
    }

    //抽象方法,子类必须实现
    public abstract void brew();
    public abstract void addCondiments();


    //钩子方法,hook  子类可以实现也可以不实现  父类已经先实现一下
    public boolean wantCondimentsHook(){
        return true;
    }
}
package templateMethod.good;

/**
 * 泡咖啡的
 */
public class Coffee extends HotDrink{

    @Override
    public void brew() {
        System.out.println("Brewing Coffee!");
    }

    @Override
    public void addCondiments() {
        System.out.println("Adding sugar and milk!");
    }
}
package templateMethod.good;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * 泡热饮
 */
public class Tea extends HotDrink{

    @Override
    public void brew() {
        System.out.println("Brewing Tea!"); //个性化的
    }

    @Override
    public void addCondiments() {
        System.out.println("Adding Lemon!");
    }

    //重写钩子方法
    @Override
    public boolean wantCondimentsHook() {
        System.out.println("Condiments, yes or no ? please input(y/n): ");
        BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
        String result = "";
        try {
            result = cin.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if(result.equals("n")) return false;
        else return true;
    }
}

测试类:

package templateMethod.good;
public class MyTest {
    public static void main(String[] args) {
        HotDrink coffee = new Coffee();
        HotDrink tea = new Tea();

        coffee.prepareRecipe();
        System.out.println("----------------tea--(implements the hook method)--------------");
        tea.prepareRecipe();
    }
}

运行结果:
这里写图片描述


Sort排序算法应用模板方法设计模式

  • 排序(sort)算法是模板模式的一个应用;
  • 对象的排列方式并不是完全相同, 所以需要排序(sort)算法compareTo()可以按需要定制(子类去实现), 但排序方法的结构不变(模板方法);
  • 需要实现(implement)接口Comparable, 并实现接口的方法public int compareTo(Object object), 才可以使用Arrays.sort()进行排序(定制);

这里写图片描述

package templateMethod.sort;

public class Duck implements Comparable<Duck> {
    String name;
    int weight;

    public Duck(String name, int weight) {
        this.name = name;
        this.weight = weight;
    }

    public int compareTo(Duck o2) {

        Duck otherDuck = o2;

        if (this.weight < otherDuck.weight) {
            return -1;
        } else if (this.weight == otherDuck.weight) {
            return 0;
        } else {        // this.weight > otherDuck.weight
            return 1;
        }
    }


    public String toString() {
        return name + " weighs " + weight;
    }

}
package templateMethod.sort;

import java.util.Arrays;

public class MyTest {

    public static void main(String[] args) {
        Duck[] ducks = { 
                        new Duck("Daffy", 8), 
                        new Duck("Dewey", 2),
                        new Duck("Howard", 7),
                        new Duck("Louie", 2),
                        new Duck("Donald", 10), 
                        new Duck("Huey", 2)
         };

        System.out.println("Before sorting:");
        display(ducks);

        Arrays.sort(ducks);

        System.out.println("\nAfter sorting:");
        display(ducks);
    }


    public static void display(Duck[] ducks) {
        for (Duck d : ducks) {
            System.out.println(d);
        }
    }
}

这里写图片描述


好莱坞原则

这里写图片描述

  • 子类相当于明星,你做好个性化的就好;
  • 步骤之类的,让经纪人(父类(做过程))做;
  • 好莱坞原则则是一种用在创建框架或组件上的一种技巧,好让底层组件能够被挂钩计算,而又不会让高层组件依赖底层组件,它是创建一个有弹性的设计,允许底层结构能够互相操作,而又防止太过于依赖。

猜你喜欢

转载自blog.csdn.net/zxzxzx0119/article/details/81709199