代码复用神器,模板模式实操分享(上)

简介: 模板模式,顾名思义,定义一个模板,将部分逻辑以具体方法或者具体构造函数的形式实现,在抽象类中声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现,这就是模板方法模式的用意。

一、介绍

模板模式,顾名思义,定义一个模板,将部分逻辑以具体方法或者具体构造函数的形式实现,在抽象类中声明一些抽象方法来迫使子类实现剩余的逻辑。

不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现,这就是模板方法模式的用意。

模板模式涉及到三个角色:

  • 抽象类(AbstractClass):实现了模板方法,定义了算法的骨架;
  • 具体类(ConcreteClass):实现抽象类中的抽象方法,已完成完整的算法;
  • 客户角色:客户类提出使用具体类的请求;

二、示例

举个例子,以早上起床到上班所需要的操作为例,大致流程可以分为以下几步:穿衣服、刷牙、洗脸、吃早餐等。男生和女生的操作可能有些区别。

我们创建一个抽象的类,定义好大致的操作流程,如下:

/**
 * 抽象类
 */
public abstract class AbstractPerson {
    /**
     * 定义操作流程
     */
    public void prepareGoWorking(){
        dressing();//穿衣服
        brushTeeth();//刷牙
        washFace();//洗脸
        eatBreakFast();//吃早餐
    }
    /**穿衣服*/
    protected abstract void dressing();
    /**刷牙*/
    protected void brushTeeth(){
        System.out.println("刷牙");
    }
    /**洗脸*/
    protected void washFace(){
        System.out.println("洗脸");
    }
    /**吃早餐*/
    protected abstract void eatBreakFast();
}

因为男生和女生的行为不一样,我们分别创建两个具体类,如下:

/**
 * 男生
 * 具体实现类
 */
public class ManPerson extends AbstractPerson{
    @Override
    protected void dressing() {
        System.out.println("穿西装");
    }
    @Override
    protected void eatBreakFast() {
        System.out.println("直接在公司吃早餐");
    }
}
/**
 * 女生
 * 具体实现类
 */
public class WomanPerson extends AbstractPerson{
    @Override
    protected void dressing() {
        System.out.println("穿休闲衣服");
    }
    @Override
    protected void eatBreakFast() {
        System.out.println("在家弄点吃的,或者在外面买一点小吃");
    }
}

创建一个客户端,实现如下:

public class TemplateClient {
    public static void main(String[] args) {
        //男生起床步骤
        ManPerson manPerson = new ManPerson();
        System.out.println("-----男生起床步骤----");
        manPerson.prepareGoWorking();
        System.out.println("-----女生起床步骤----");
        //女生起床步骤
        WomanPerson womanPerson = new WomanPerson();
        womanPerson.prepareGoWorking();
    }
}

输出结果:

-----男生起床步骤----
穿西装
刷牙
洗脸
直接在公司吃早餐
-----女生起床步骤----
穿休闲衣服
刷牙
洗脸
在家弄点吃的,或者在外面买一点小吃

当然,模版模式的玩法,还不仅仅只有这些,还可以在模版模式中使用挂钩(hook)

什么是hook呢?存在一个空实现的方法,我们称这种方法为hook。子类可以视情况来决定是否要覆盖它。

还是以上面为例子,比如吃完早餐就要出门上班,选择什么交通工具呢?

抽象类新增方法hook(),内容如下:

/**
 * 抽象类
 */
public abstract class AbstractPerson {
    /**
     * 定义操作流程
     */
    public void prepareGoWorking(){
        dressing();//穿衣服
        brushTeeth();//刷牙
        washFace();//洗脸
        eatBreakFast();//吃早餐
        hook();//挂钩
    }
    /**穿衣服*/
    protected abstract void dressing();
    /**刷牙*/
    protected void brushTeeth(){
        System.out.println("刷牙");
    }
    /**洗脸*/
    protected void washFace(){
        System.out.println("洗脸");
    }
    /**吃早餐*/
    protected abstract void eatBreakFast();
    /**挂钩*/
    protected void hook(){};
}

男生具体实现类,重写hook()方法,内容如下:

/**
 * 男生
 * 具体实现类
 */
public class ManPerson extends AbstractPerson{
    @Override
    protected void dressing() {
        System.out.println("穿西装");
    }
    @Override
    protected void eatBreakFast() {
        System.out.println("直接在公司吃早餐");
    }
    @Override
    protected void hook() {
        System.out.println("乘地铁上班");
    }
}

运行测试类,男生具体实现类,输出结果:

-----男生起床步骤----
穿西装
刷牙
洗脸
直接在公司吃早餐
乘地铁上班

当然,还有其他的玩法,比如女生洗完脸之后,可能需要化妆,我们再次将抽象类进行处理,内容如下:

/**
 * 抽象类
 */
public abstract class AbstractPerson {
    /**
     * 定义操作流程
     */
    public void prepareGoWorking(){
        dressing();//穿衣服
        brushTeeth();//刷牙
        washFace();//洗脸
        //是否需要化妆,默认不化妆
        if(isMakeUp()){
            System.out.println("进行化妆");
        }
        eatBreakFast();//吃早餐
        hook();//挂钩
    }
    /**是否需要化妆方法*/
    protected boolean isMakeUp(){
        return false;
    }
    /**穿衣服*/
    protected abstract void dressing();
    /**刷牙*/
    protected void brushTeeth(){
        System.out.println("刷牙");
    }
    /**洗脸*/
    protected void washFace(){
        System.out.println("洗脸");
    }
    /**吃早餐*/
    protected abstract void eatBreakFast();
    /**挂钩*/
    protected void hook(){};
}

女生具体实现类,重写isMakeUp()方法,内容如下:

/**
 * 女生
 * 具体实现类
 */
public class WomanPerson extends AbstractPerson{
    @Override
    protected void dressing() {
        System.out.println("穿休闲衣服");
    }
    @Override
    protected void eatBreakFast() {
        System.out.println("在家弄点吃的,或者在外面买一点小吃");
    }
    @Override
    protected boolean isMakeUp() {
        return true;
    }
}

运行测试类,女生具体实现类,输出结果:

-----女生起床步骤----
穿休闲衣服
刷牙
洗脸
进行化妆
在家弄点吃的,或者在外面买一点小吃
相关文章
|
2月前
|
设计模式 Java 数据库
Java设计模式精讲:让代码更优雅、更可维护
【4月更文挑战第2天】**设计模式是解决软件设计问题的成熟方案,分为创建型、结构型和行为型。Java中的单例模式确保类仅有一个实例,工厂方法模式让子类决定实例化哪个类。适配器模式则协调不兼容接口间的合作。观察者模式实现了一对多依赖,状态变化时自动通知相关对象。学习和适当应用设计模式能提升代码质量和可维护性,但需避免过度使用。设计模式的掌握源于实践与不断学习。**
Java设计模式精讲:让代码更优雅、更可维护
|
2月前
|
设计模式 算法
二十三种设计模式全面解析-深入解析模板方法模式的奇妙世界
二十三种设计模式全面解析-深入解析模板方法模式的奇妙世界
|
2月前
|
设计模式
二十三种设计模式全面解析-访问者模式的高级应用和实践技巧
二十三种设计模式全面解析-访问者模式的高级应用和实践技巧
|
2天前
|
设计模式 缓存 算法
编写高效的Java工具类:实用技巧与设计模式
编写高效的Java工具类:实用技巧与设计模式
|
2月前
|
设计模式 传感器 数据处理
探索设计模式的魅力:为什么你应该了解装饰器模式-代码优化与重构的秘诀
装饰器模式是一种设计模式,它允许在运行时向对象添加额外的职责,而无需修改其代码。这种模式提供了一种动态扩展对象功能的方法,同时保持了对象的单一职责原则。本文介绍了装饰器模式的基本概念、原理、优势、适用场景、实现方法、最佳实践和注意事项。通过装饰器模式,可以将多个行为组合成一个更复杂的行为,而无需使用继承或大量的接口实现。装饰器模式适用于需要对一个对象进行一系列的增强处理的情况,而这些增强处理可以以一种松耦合的方式进行组合。通过使用装饰器模式,可以提高代码的可维护性、可扩展性和灵活性,使系统更加灵活和易于维护
67 1
探索设计模式的魅力:为什么你应该了解装饰器模式-代码优化与重构的秘诀
|
2月前
|
设计模式 存储 缓存
二十三种设计模式全面解析-探索解释器模式的高级应用和优化技巧:解锁代码解析的新境界
二十三种设计模式全面解析-探索解释器模式的高级应用和优化技巧:解锁代码解析的新境界
|
Java
【Java面向对象】多态的详细介绍,简单易懂,看这一篇就够了
【Java面向对象】多态的详细介绍,简单易懂,看这一篇就够了
133 0
|
设计模式 算法 uml
CRUD很无聊?一起学设计模式吧!--模板模式​
CRUD很无聊?一起学设计模式吧!--模板模式​
44 0
|
设计模式 算法 搜索推荐
23个小案例带你吃透23种设计模式(三)
23个小案例带你吃透23种设计模式
128 0
23个小案例带你吃透23种设计模式(三)
|
设计模式 存储 算法
23个小案例带你吃透23种设计模式(二)
23个小案例带你吃透23种设计模式
127 0
23个小案例带你吃透23种设计模式(二)