• 13.java设计模式之模板模式


    基本需求

    • 制作豆浆的流程 选材--->添加配料--->浸泡--->放到豆浆机打碎
    • 通过添加不同的配料,可以制作出不同口味的豆浆
    • 选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的
    • 通过模板方法可以完成

    基本介绍

    • 模板方法模式(Template Method),又叫模板模式(Template),在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行

    • 模板方法模式 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤,这种类型的设计模式属于行为型模式

    • UML类图(原理)

      • 说明

        • AbstractClass:抽象类,其中的template()为模板方法

          • public final void template() {
               // 在模板方法内部调用其他方法 规定算法的具体流程,这些方法可以是抽象的,也可以不是抽象的
               // 抽象的方法就交由子类实现,子类不改变算法的结构重定义算法的某些步骤
               // 模板方法内部调用自身实现的方法,可作为钩子方法,让子类有选择的去实现
               operation1();
               operation2();
            }
            
        • ConcreationClass:实现类,对template()方法内部所使用的方法进行实现,对钩子方法可以选择性的实现,不实现则使用父类的实现

    • UML类图(案例)

    • 代码实现

      • public abstract class SoyMilk {
        
           // 模板方法 使用final 不能让子类重写,定义好具体的算法流程,其实现子类去实现
           public final void make() {
               select();
               if (isAdd()) {
                   // 使用钩子方法判断是否需要加配料 默认加
                   add();
               }
               soak();
               beat();
           }
        
           // 添加配料方法 ,不同品种的豆浆,加的配料不一样
           public abstract void add();
        
           // 该方法为钩子方法,子类可根据情况是否实现该方法
           public boolean isAdd() {
               return true;
           }
        
           public void select() {
               System.out.println("选择好的新鲜黄豆");
           }
        
           public void soak() {
               System.out.println("黄豆和配料开始浸泡,需要3小时");
           }
        
           public void beat() {
               System.out.println("黄豆和配料放到豆浆机去打碎");
           }
        
        }
        
        // 子类一
        class RedBeanSoyMilk extends SoyMilk {
           // 重写添加方法
           @Override
           public void add() {
               System.out.println("添加上好的红豆");
           }
        
        }
        
        // 子类二
        class PeanutSoyMilk extends SoyMilk {
           // 重写添加方法
           @Override
           public void add() {
               System.out.println("添加上好的花生");
           }
        
        }
        
        // 子类三
        class PureSoyMilk extends SoyMilk {
           // 重写添加方法 和 钩子方法
           @Override
           public void add() {
               System.out.println("添加上好的花生");
           }
        
           @Override
           public boolean isAdd() {
               return false;
           }
        }
        
      • public class Client {
           public static void main(String[] args) {
               // 制作红豆豆浆 调用模板方法
               SoyMilk redBeanSoyMilk = new RedBeanSoyMilk();
               redBeanSoyMilk.make();
               // 制作花生豆浆 调用模板方法
               SoyMilk peanutSoyMilk = new PeanutSoyMilk();
               peanutSoyMilk.make();
               // 制作纯豆浆 重写了钩子方法 调用模板方法
               SoyMilk pureSoyMilk = new PureSoyMilk();
               pureSoyMilk.make();
           }
        }
        

    spring源码

    • 在spring的IOC容器中就使用到了模板模式
    • UML类图
      • 说明
        • refresh()方法调用该类很多方法,也就是模板方法
        • obtainFreshBeanFactory()方法内部调用了refreshBeanFactory()和getBeanFactory()方法,这两个方法是抽象方法,交由了子类去完成
        • postProcessBeanFactory()和onRefresh()方法为钩子方法,在AbstractApplicationContext()内部进行了空实现,子类可以有选择的进行重写

    注意事项

    • 基本思想是:算法只存在于一个地方,也就是在父类中,容易修改。需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改
    • 实现了最大化代码复用。父类的模板方法和已实现的某些步骤会被子类继承而直接使用
    • 既统一了算法,也提供了很大的灵活性。父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步骤的实现
    • 该模式的不足之处:每一个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大
    • 一般模板方法都加上 final 关键字, 防止子类重写模板方法
    • 模板方法模式使用场景:当要完成在某个过程,该过程要执行一系列步骤 ,这一系列的步骤基本相同,但其个别步骤在实现时可能不同,通常考虑用模板方法模式来处理
  • 相关阅读:
    REP开发技巧
    css grid栅格布局
    flex学习, 尝试布局一个计算器
    sublime text html插件emmet
    flex布局
    SQL Server为字段添加默认值
    windows和linux文件输
    python eric6 IDE
    git撤销修改
    pyQt5
  • 原文地址:https://www.cnblogs.com/xiaokantianse/p/14034215.html
Copyright © 2020-2023  润新知