JavaSE|模板设计模式

本文介绍了模板设计模式,遵循开闭原则,通过实例展示了如何将咖啡和茶的冲泡过程进行抽象,提取共性部分到基类,使得子类可以自定义不同步骤,从而实现代码复用和算法结构不变的扩展。同时,文章讨论了模板设计模式的优化、优点,如代码复用和符合开闭原则,以及可能带来的缺点,即可能导致类的数量增加。
摘要由CSDN通过智能技术生成

开闭原则(OCP):一个软件实体如类、模块和函数应该对扩展开放、对修改关闭。
讲模板设计模式之前,我们先来看一下星巴克咖啡冲泡师傅的训练手册。

星巴克咖啡冲泡法

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

星巴克茶冲泡法

  1. 将水煮沸
  2. 用沸水浸泡茶叶
  3. 把茶倒进杯子
  4. 加柠檬

如果将这两个泡法分别写个类来实现的话,我们发现会有很多代码重复。既然茶和咖啡是如此相似,因此我们应该将公同的部分抽取出来,放进一个基类中。

模板设计模式

模板方法定义了一个算法的步骤,并允许子类为一个或者多个步骤提供具体实现。
范例:模板设计模式的实现

/**
 * 咖啡因饮料是一个抽象类
 */
abstract class CaffeineBeverage {
    /**
     * 现在用同一个prepareRecipe()方法处理茶和咖啡。
     * 声明为final的原因是我们不希望子类覆盖这个方法!
     */
    final void prepareRecipe() {
        boilWater();//将水煮沸
        brew();//用热水泡饮料
        pourInCup();//将饮料倒进杯子里
        addCondiments();//在饮料中假如适当的调料
    }
    /**
     * 咖啡和茶处理这些方法不同,因此这两个方法必须被声明为抽象,留给子类实现
     */
    abstract void brew();
    abstract void addCondiments();
    void boilWater() {
        System.out.println("Boiling water");
    }
    void pourInCup() {
        System.out.println("Pouring into cup");
    }
}
class Tea extends CaffeineBeverage {
    void brew() {
        System.out.println("Steeping the tea");
    }
    void addCondiments() {
        System.out.println("Adding Lemon");
    }
}
class Coffee extends CaffeineBeverage {
    void brew() {
        System.out.println("Dripping Coffee through filter");
    }
    void addCondiments() {
        System.out.println("Adding Sugar and Milk");
    }
}

public class Interview {
    public static void main(String[] args) {

     CaffeineBeverage caffeineBeverage=new Tea();
     caffeineBeverage.prepareRecipe();
     CaffeineBeverage caffeineBeverage1=new Coffee();
     caffeineBeverage1.prepareRecipe();
       
    }
}

模板设计模式(优化)

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

import java.util.Scanner;

abstract class CaffeineBeverage {
    final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
// 如果顾客想要饮料我们才调用加料方法
        if (customerWantsCondiments()){
            addCondiments();
        }
    }
    abstract void brew();
    abstract void addCondiments();
    void boilWater() {
        System.out.println("Boiling water");
    }
    void pourInCup() {
        System.out.println("Pouring into cup");
    }
    /**
     * 钩子方法
     * 超类中通常是默认实现
     * 子类可以选择性的覆写此方法
     * @return
     */
    boolean customerWantsCondiments() {
        return true;
    }
}
class Tea extends CaffeineBeverage {
    void brew() {
        System.out.println("Steeping the tea");
    }
    void addCondiments() {
        System.out.println("Adding Lemon");
    }
}
class Coffee extends CaffeineBeverage {
    void brew() {
        System.out.println("Dripping Coffee through filter");
    }
    void addCondiments() {
        System.out.println("Adding Sugar and Milk");
    }
    /**
     * 子类覆写了钩子函数,实现自定义功能
     * @return
     */
    public boolean customerWantsCondiments() {
        String answer = getUserInput();
        if (answer.equals("y")) {
            return true;
        }else {
            return false;
        }
    }
    private String getUserInput() {
        String answer = null;
        System.out.println("您想要在咖啡中加入牛奶或糖吗 (y/n)?");
        Scanner scanner = new Scanner(System.in);
        answer = scanner.nextLine();
        return answer;
    }
}

public class Interview {
    public static void main(String[] args) {

     CaffeineBeverage caffeineBeverage=new Tea();
     caffeineBeverage.prepareRecipe();
     CaffeineBeverage caffeineBeverage1=new Coffee();
     caffeineBeverage1.prepareRecipe();
       
    }
}

在这里插入图片描述

模板设计模式的优缺点

优点
在这里插入图片描述

优点

(1)具体细节步骤实现定义在子类中,子类定义详细处理算法是不会改变算法整体结构。
(2)代码复用的基本技术,在数据库设计中尤为重要。
(3)存在一种反向的控制结构,通过一个父类调用其子类的操作,通过子类对父类进行扩展增加新的行为,符合“开闭原则”。

缺点

每个不同的实现都需要定义一个子类,会导致类的个数增加,系统更加庞大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值