软件设计模式—模板方法模式

前篇——软件设计模式-基础
前篇——软件设计模式-三种工厂模式
前篇——软件设计模式-装饰者模式
前篇——软件设计模式-单例模式
前篇——软件设计模式-原型模式
前篇——软件设计模式-命令模式
前篇——软件设计模式-策略模式

它是一种类行为型模式

1.问题引入

泡茶与泡咖啡的流程
泡茶:烧水、加茶叶、倒水、加柠檬。
泡咖啡:烧水、加咖啡粉、倒水、加糖或者牛奶。
冲泡方法大致相似,我们将共同的部分抽取出来,放入一个基类中。

2.模板方法模式

定义算法架构的模式,步骤延迟到子类

2.1 定义

定义一个操作中的算法骨架,而将一些步骤延迟到子类之中,模板方法子类可以不改变一个算法的结构,即可重新定义该算法的某些特定步骤。

2.2 模板方法模式实现

2.2.1 e.g.1(实现问题)

模板方法实现引入的问题
在这里插入图片描述

//抽象模板(AbstractDrink)
public abstract class AbstractDrink{
    //抽象方法(增加原料)
    public abstract void add_X();
    //抽象方法(增加其他的东西)
    public abstract void add_Other();
    //给钩子方法判断的变量
    public String result;
    //钩子方法(还需要其他东西吗)
    public boolean needOtherThing(){
        if(result == "yes"){
            System.out.println(result);
            return true;
        }
        else if(result == "no"){
            System.out.println(result);
            return false;
        }else
        System.out.println(result);
        return false;
    }
    //模板方法(使用直接调用就完事了)
    public void templeMethod(){
        boilWater();
        add_X();
        pourInCup();
        if(needOtherThing()) {
            add_Other();
        }
        else{
            System.out.println("原味即可,啥也不用加");
        }
    }
    //基本方法(功能共通部分)(烧水)
    public final void boilWater(){
        System.out.println("把水烧开");
    }
    //基本方法(功能共通部分)(倒在杯子里)
    public final void pourInCup(){
        System.out.println("倒在杯子里");
    }
}
//具体模板(咖啡)
public class Coffee extends AbstractDrink{
	//在构造方法中给父类的result赋值,判断是否要加点糖,相当于顾客说的话
    public Coffee(String result) {
        super.result = result;
	}
    public static String coffee = "咖啡";
    public static String suger = "糖";
    //实现的抽象方法add_X,根据这个方法决定到底做什么
    public void add_X(){
        System.out.println("加入原材料:"+ coffee);
    }
    //实现辅料的抽象方法
    public void add_Other(){
        System.out.println("辅助添加:"+ suger );
    }
}
//具体模板(茶)
//解释和上面咖啡类似
public class Tea extends AbstractDrink{
    public Tea(String result) {
        super.result = result;
	}
    public static String tea = "茶";
    public static String lemon = "柠檬";
    public void add_X(){
        System.out.println("加入原材料:" + tea);
    }
    public void add_Other(){
        System.out.println("辅助添加:" + lemon);
    }
}
//测试类
public class test{
    public static void main(String[] args) {
        Coffee coffee1 = new Coffee("yes");
        coffee1.templeMethod();
        System.out.println("-------------------");
        AbstractDrink tea1 = new Tea("no");
        tea1.templeMethod();
    }
}

2.3 结构

2.3.1 角色

  1. 抽象模板(AbstractDrink):抽象模板是一个抽象类。抽象模板定义了若干个方法表示一个算法的各个步骤。这些方法既有抽象方法,也有非抽象方法。在抽象模板中还定义了一个称作模板方法的方法。模板方法就是可以包含有具体抽象方法的调用,也可以包含有抽象方法的调用。
  2. 具体模板(TeaCoffee):是抽象模板的子类,实现抽象模板中的抽象方法。

2.3.2 抽象模板中的方法

a. 模板方法(templeMethod()):是定义在抽象类中的、把基本操作方法组合在一起形成一个总算法或一个总行为的方法,并按照某种顺序调用包含的基本方法
b. 基本方法:基本方法是实现算法各个步骤的方法,是模板方法的组成部分

  1. 抽象方法(add_X()add_Other()):在抽象类中声明,由具体子类实现
  2. 具体方法(boilWater(),pourInCup()):在抽象类中已经实现,在具体子类中可以继承或重写它。
  3. 钩子方法(needOtherThing()):在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。

用final来修饰父类中不变(不能被重写)的方法
模板方法模式封装了一个算法步骤,并允许子类为一个或多个步骤方法提供实现,模板模式可以在使子类在不改变算法结构的情况下,重新定义算法中的某些步骤。

2.4 优缺点

2.4.1 优点

  1. 易扩展:一般抽象类中模板方法不易改变,抽象方法易改变,通过增加实现类,一般很容易扩展,符合开闭原则。
  2. 便于维护
  3. 灵活:因为钩子方法,子类的实现可以影响父类中逻辑的运行

2.4.2 缺点

  1. 由灵活引发的缺点:子类影响父类,给程序带来了风险
  2. 使系统过于庞大:每个不同的实现都要定义一个子类。
  3. 代码难读(子类父类相互影响)

2.5 应用场景

  1. 当子类有统一的操作步骤或操作过程
  2. 子类具有不同的操作细节
  3. 存在多个具有同样操作步骤的应用场景,但某些具体的操作细节不同

3. tip

3.1 策略模式 和 模板方法模式

细心的童鞋发现策略模式和模板方法模式都是对算法进行处理。

3.1.1 两者的区别

策略模式着重点在:使用委派的方法提供不同的算法行为。核心是:方法的封装
模板方法模式着重点在:使用继承的方法提供不同的算法行为。核心是:方法调用的顺序

3.1.2 两者的联系

可以组合使用:模板方法重在封装算法骨架。策略模式重在封装算法的实现。

3.2 final关键字

final知识点来自——“努力的小海龟”的博客
final关键字是我们经常使用的关键字之一,它的用法有很多,但是并不是每一种用法都值得我们去广泛使用。它的主要用法有以下四种:

  1. 用来修饰数据,包括成员变量和局部变量,该变量只能被赋值一次且它的值无法被改变。对于成员变量来讲,我们必须在声明时或者构造方法中对它赋值;
  2. 用来修饰方法参数,表示在变量的生存期中它的值不能被改变;
  3. 修饰方法,表示该方法无法被重写;
  4. 修饰类,表示该类无法被继承。

上面的四种方法中,第三种和第四种方法需要谨慎使用,因为在大多数情况下,如果是仅仅为了一点设计上的考虑,我们并不需要使用final来修饰方法和类。

3.3 模板方法模式迪米特法则

在模板方法模式中,子类不显示调用父类的方法,而是通过覆盖父类的方法来实现某些具体的业务逻辑。

3.3.1 好莱坞原则

父类控制对子类的调用。

3.3.2 遗留问题

在e.g.1中我们通过子类的构造方法来影响父类的行为,在一定程度违反了好莱坞原则。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值