zoukankan      html  css  js  c++  java
  • 004-行为型-02-模板方法模式(Template Method)

    一、概述

      定义了一个算法的骨架,并允许子类为一个或多个步骤提供实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤

    1.1、适用场景

      一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现

      各子类中公共的行为被提取出来并集中到一个公共父类中,从而避免代码重复

      一些方法通用,一些却在每一个子类都重新写了这一方法。

      Template Method模式一般应用在具有以下条件的应用中:

        1、具有统一的操作步骤或操作过程

        2、具有不同的操作细节

        3、存在多个具有同样操作步骤的应用场景,但某些具体的操作细节却各不相同

    1.2、优缺点

    优点:

    • 提高复用性,提取公共代码,便于维护
    • 提高扩展性
    • 符合开闭原则
    • 行为由父类控制,子类实现

    缺点:

    • 类数目增加
    • 增加了系统实现的复杂度
    • 如果父类添加新的抽象方法,所有子类都要改一遍

    注意:为防止恶意操作,一般模板方法都加上 final 关键词。

    1.3、类图角色及其职责

      

      模板方法模式的角色和职责

      1、AbstractClass:抽象类的父类

      2、ConcreteClass:具体的实现子类

      3、templateMethod():模板方法,具体步骤方法的执行顺序(步骤)

      4、method1()与method2():具体步骤方法(细节)

    1.4、演进过程

      代码来实现一下:我们举个例子,加入我们要组装汽车,步骤是,先组装车头,再组装车身,最后组装车尾,喷漆,是否需要打蜡

      这样,我们先建造AbstractClass(其中包含template模板,执行顺序)

    // 组装车(AbstractClass)
    public abstract class MakeCar {
        //定义结构里哪些方法是所有过程都是一样的可复用的,哪些是需要子类进行实现的
        //组装车头
        public abstract void makeCarHead();
    
        //组装车身
        public abstract void makeCarBody();
    
        //组装车尾
        public abstract void makeCarTail();
    
        //喷漆 都一样 统一实现
        public void makeCarPaint() {
            System.out.println("汽车喷漆");
        }
    
        //打蜡
        public abstract void makeCarDaLa();
        
        //声明一个钩子方法 需要打蜡 由用户确认 是否需要
        protected boolean needMakeCarDaLa() {
            return true;
        }
    
        //汽车组装流程(template()) 用来控制流程
        //申明为final,不希望子类覆盖这个方法,防止更改流程的执行顺序
        public final void makeCar() {
            this.makeCarHead();
            this.makeCarBody();
            this.makeCarTail();
            this.makeCarPaint();
            // 这里是否需要 交由钩子方法来决定
            if (needMakeCarDaLa()) {
                this.makeCarDaLa();
            }
        }
    }

      再新建ConcreteClass(具体的实现细节)

    //组装公交车
    public class MakeBus extends MakeCar{
    
        @Override
        public void makeCarHead() {
            System.out.println("组装公交车车头");
        }
    
        @Override
        public void makeCarBody() {
            System.out.println("组装公交车车身");
        }
    
        @Override
        public void makeCarTail() {
            System.out.println("组装公交车车尾");
        }
    
        @Override
        public void makeCarDaLa() {
    
        }
    
        @Override
        protected boolean needMakeCarDaLa() {
            return false;
        }
    }
    //  组装SUV
    public class MakeSuv extends MakeCar{
    
        @Override
        public void makeCarHead() {
            System.out.println("组装SUV车头");
        }
    
        @Override
        public void makeCarBody() {
            System.out.println("组装SUV车身");
        }
    
        @Override
        public void makeCarTail() {
            System.out.println("组装SUV车尾");
        }
    
        @Override
        public void makeCarDaLa() {
            System.out.println("组装SUV-打蜡");
        }
    }

    测试

        @Test
        public void makeCar() {
            MakeCar makeBus = new MakeBus();
            makeBus.makeCar();
    
            System.out.println("===========================");
    
            MakeCar makeSuv = new MakeSuv();
            makeSuv.makeCar();
        }

      用户不必关心具体的执行流程(步骤)

      输出

    组装公交车车头
    组装公交车车身
    组装公交车车尾
    汽车喷漆
    ===========================
    组装SUV车头
    组装SUV车身
    组装SUV车尾
    汽车喷漆
    组装SUV-打蜡

    二、扩展

      spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来,比如开启事务、获取 Session、关闭 Session 等,程序员不重复写那些已经规范好的代码,直接丢一个实体就可以保存。

      jdk:java.util.AbstractList定义一套算法模板,如get(),set()等等,由子类实现。

      servlet:javax.servlet.http.HttpServlet定义一套算法模板,如doGet()、doPost()等等,由子类实现。。

      mybatis:org.apache.ibatis.executor.BaseExecutor

  • 相关阅读:
    fiddler使用
    Laravel数据库操作
    mysql 小知识点备忘(一)
    移动端和服务器端通信
    js函数和代码片段
    tomcat9目录结构解析
    数据库三范式的理解
    win10修改hosts文件
    Java十六进制字符串与二进制数组互转、&0xff的作用
    15、SpringBoot实现Excel的导入导出
  • 原文地址:https://www.cnblogs.com/bjlhx/p/11421119.html
Copyright © 2011-2022 走看看