模板设计模式 -- 给大佬递咖啡

设计原则:

开闭原则(OCP):是5大设计原则中最基础的设计原则,指的是一个软件实体如类、接口等应该对扩展开放,对修改关闭。

模板设计模式(模板方法) :基于抽象类的设计模式

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

第三方:模板类,将核心算法与具体子类相分离,子类只需要覆写具体的某几步流程即可。

特点:在一个方法中定义一个算法的骨架(如冲泡饮料流程),而将一些步骤延迟到子类中实现。

优点:模板模式可以使得子类在不改变核心算法的基础上,具体实现算法中的某些步骤。

以星巴克冲冲咖啡或泡茶为例:
冲咖啡流程:① 烧水,② 冲泡咖啡,③ 将咖啡倒入杯中,④ 加入牛奶和糖
泡茶流程:① 烧水,② 浸泡茶包,③ 将茶倒入杯中,④ 加入柠檬 (可不选)

1. 问题:我们发现咖啡与茶在制作过程中,烧水与倒入杯中两个过程是重复操作,如果按照一般的编代码的格式来写势必会产生大量的重复代码。

  • 此时就应该想到可以将烧水与倒入杯中这两个方法提取出来放在基类 (父类) 中,让茶与咖啡都继承此父类。

2. 问题:虽然咖啡和茶是确实是两种不同的东西,但是它们都算是饮料吧。观察咖啡和茶的冲泡法我们会发现,两种冲泡法都采用了相同的算法:① 烧水,② 用热水泡饮料,③ 把饮料倒进杯子,④ 加入调料。

  • 此时应该想到抽象方法, 把用热水泡饮料和加入调料这两个方法抽象化,放到子类中根据到底是咖啡还是茶来具体实现。

3. 问题:并不是所有的顾客都想往饮料里面加东西,咖啡一般是加糖和牛奶没什么毛病,可是茶的话就不一定了。

  • 钩子方法(hook方法):默认不做事的方法,子类可以视情况而定是否需要覆写。把是否加调料封装为钩子方法。
import java.util.Scanner;

//基类声明为抽象类的原因是其子类必须实现其操作
abstract class CaffeeineBeverage {
    //模板方法,模拟饮料机的按键,被声明为final是为了防止子类修改
    public final void perpareRecipe() {
        boilWater();
        brewBeverage();
        pourIncup();
        //如果顾客想要饮料我们才调用加料方法
        if(isCustomerWantsConditions()) {
            addCondiments();
        }   
    }

    //烧水和倒入杯中是一样的,具体操作且共用的方法定义在超类中可以被模板方法或子类直接使用
    public void boilWater() {
        System.out.println("将水烧开");
    }
    public void pourIncup() {
        System.out.println("将饮料倒入杯中");
    }
    
    //泡什么饮料以及加什么调料不一样,抽象方法,具体操作延迟到子类中实现
    public abstract void brewBeverage();
    public abstract void addCondiments();
    
    //钩子方法,钩子方法是一类"默认不做事的方法",子类可以视情况决定要不要覆盖它
    public boolean isCustomerWantsConditions() {
        return true;
    }
}

//咖啡类和茶类现在都是依赖超类来处理冲泡流程,烧水和倒入杯中从父类继承下来了,因此只需要各自处理冲泡和加调料部分即可
class Coffee extends CaffeeineBeverage {
    public void brewBeverage() {
        System.out.println("冲泡咖啡");
    }
    public void addCondiments() {
        System.out.println("加入糖和牛奶");
    }
}
class Tea extends CaffeeineBeverage {
    public void brewBeverage() {
        System.out.println("浸泡茶包");
    }
    public void addCondiments() {
        System.out.println("加入柠檬");
    }
    //钩子方法子类视情况而定是否需要覆写,默认值是true
    public boolean isCustomerWantsConditions() {
        System.out.println("您需要加柠檬吗? y:需要  n:不需要");
        Scanner scanner = new Scanner(System.in);
        String str = scanner.nextLine();
        if(str.equals("y")) {
            System.out.println("客户想要柠檬");
            return true;
        } else {
            System.out.println("客户什么都不加");
            return false;
        }
    }
}

public class Test {
    public static void main(String[] args) {
        Coffee coffee = new Coffee();
        System.out.println("给大佬递咖啡");
        coffee.perpareRecipe();
        System.out.println("==========");
        Tea tea = new Tea();
        System.out.println("给大佬递茶");
        tea.perpareRecipe();
    }
}

在这里插入图片描述
模板类的组成:

final修饰的核心算法;

abstract修饰的抽象方法,延迟到子类中实现;

③ 普通具体方法,所有子类都一样,子类直接使用即可;

④ 钩子方法(hook方法)。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值