【设计模式】模板方法模式

解释:

  模板方法模式也是也是比较容易理解的,就比如说做饭,同样的步骤不同的人做味道是不一样的。或者是造汽车,同样的步骤,造车厂商不一样,造出来的汽车质量不同。这就是模板方法模式.

定义:

  它定义一个操作中的算法的框架,而将一些步骤延迟到了子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些步骤。

核心:

  处理的步骤父类中早已定义好,具体的实现延迟到子类中去完成。

模板方法的角色:

  1.抽象模板角色:它一般是一个抽象类或者接口,它抽象出操作算法骨架。

  2.具体抽象模板角色:它实现了抽象模板角色的方法,它是操作算法骨架业务的具体化。

模板方法的优点:

  1.封装不变部分,扩展可变部分。

  2.提取了公共代码,便于维护。

  3.行为由父类控制,子类实现。

模板方法的缺点:

  1.每一个不同的实现都需要一个子类来实现,这样导致类的个数增加。

模板模式的使用场景:

  1.实现一个算法时,基本步骤很固定,但是某些部分易变,易变的部分可以抽离出来,由子类实现。

具体使用描述:

  1. 使用抽象类定义模板类,并在其中定义所有的基本方法、模板方法,钩子方法,不限数量,以实现功能逻辑为主。其中基本方法使用final修饰,其中要调用基本方法和钩子方法,基本方法和钩子方法可以使用protected修饰,表明可被子类修改。

  1. 定义实现抽象类的子类,重写其中的模板方法,甚至钩子方法,完善具体的逻辑。

 

代码实现

public abstract class DBTemplate {
    protected abstract void open();
    protected abstract void select();
    protected abstract void close();
    //一个搜索模板
    public final void selectTemplate(){
        open();
        select();
        close();
    }
}

public class MysqlDB extends DBTemplate {
    @Override
    protected void open() {
        System.out.println("开启mysql");
    }
    @Override
    protected void select() {
        System.out.println("输入mysql查询语句");
    }
    @Override
    protected void close() {
        System.out.println("关闭mysql");
    }
}

public class Test {
    public static void main(String[] args) {
        DBTemplate mysql = new MysqlDB();
        mysql.selectTemplate();
    }
}

//开启mysql
//输入mysql查询语句
//关闭mysql

 

可以加上钩子函数

public abstract class DBTemplate {
    protected DBTemplate(String name){
        this.name = name;
    }
    protected String name;
    protected abstract void open();
    protected abstract void select();
    protected abstract void close();
    protected abstract void update();

    //可以定义一个钩子函数
    protected boolean hookMethod(){
        return true;
    };
    //一个搜索模板
    public final void selectTemplate(){
        open();
        select();
        close();
        if(hookMethod()){
            update();
        }
    }
}

public class MysqlDB extends DBTemplate {
    public boolean isUse;
    protected MysqlDB(String name) {
        super(name);
    }
    protected MysqlDB(String name,boolean isUse) {
        this(name);
        this.isUse = isUse;
    }
    @Override
    protected void open() {
        System.out.println("开启mysql");
    }
    @Override
    protected void select() {
        System.out.println("输入mysql查询语句");
    }
    @Override
    protected void close() {
        System.out.println("关闭mysql");
    }
    @Override
    protected void update() {
        System.out.println("更新mysql");
    }
    @Override
    protected boolean hookMethod() {
        return isUse;
    }
}

public class Test {
    public static void main(String[] args) {
        //传true 就会调用update方法
        DBTemplate mysql = new MysqlDB("测试",false);
        mysql.selectTemplate();
    }
}

//开启mysql
//输入mysql查询语句
//关闭mysql

 

其他应用 

  JDK 中也有模板方法的身影,比如:AbstractQueuedSynchronizer、多线程 AQS 的实现。Dubbo 中也有模板方法的使用,比如:Dubbo 中负载均衡算法的实现。SpringBatch 中也有,如果你用过这个框架的话!tomcat 的 LifecycleBase 也是模板方法模式,Spring 中的 JdbcTemplate。

  平时开发的时候,比如做一个excel导出功能,也可以将其进行分解,之后根据不同公司的要求,去导出不同的excel。

  如打刻项目,使用hutool poi进行excel导出的时候,有三个管理员角色、普通用户角色、打印、刻录六种日志,他们导出的excel列头都有区别。有的excel还要求有标题,此时就可以使用模板方法模式,步骤大概为:

    1.首先获取数据源

    2.根据不同类型的日志定义sheet页的列头并写入数据

    3.压缩excel到zip下并加密

    4.根据结果记录日志

 

参考:

https://www.jb51.net/article/166685.htm

https://baijiahao.baidu.com/s?id=1639309117007251878&wfr=spider&for=pc

 

posted @ 2021-08-30 17:30  夏夜凉凉  阅读(72)  评论(0编辑  收藏  举报