【JavaSE】Java设计模式详解(二)抽象模板模式

简介: 文章目录1 问题引入2 初步优化(每个类内部)3 抽象模板设计写在最后

1 问题引入

✈️ 老套路啦!我们先来看一个需求:


有多个类,假设有三个:小学生类Pupil、中学生类MStudent、大学生类CStudent ,其中每个类都有不同的 homework() 方法,要求你统计各自完成作业需要的时间。


Tips: 在实现需求时,我们假设小学生、中学生、大学生完成作业的时间是依次增加的,将其作业的任务设置成一个方法 homework,用于完成作业并计算完成作业的时间。


🍌 参考代码:


⭐️ Pupil类:

class Pupil{
    private String name = "小学生";
    public String getName(){
        return this.name;
    }
    // 完成作业
    public void homework(){
        long start = System.currentTimeMillis();
        long time = 0;
        for (int i = 0; i < 100000; i++) {
            time += i;
        }
        long end = System.currentTimeMillis();
        System.out.println(getName() + "完成作业用时:" + (end-start) + "h");
    }
}

⭐️ MStudent类:

class MStudent{
    private String name = "中学生";
    public String getName(){
        return this.name;
    }
    // 完成作业
    public void homework(){
        long start = System.currentTimeMillis();
        long time = 0;
        for (int i = 0; i < 9000000; i++) {
            time += i;
        }
        long end = System.currentTimeMillis();
        System.out.println(getName() + "完成作业用时:" + (end-start) + "h");
    }
}


⭐️ CStudent类:

class CStudent{
    private String name = "大学生";
    public String getName(){
        return this.name;
    }
    // 完成作业
    public void homework(){
        long start = System.currentTimeMillis();
        long time = 0;
        for (int i = 0; i < 90000000; i++) {
            time += i;
        }
        long end = System.currentTimeMillis();
        System.out.println(getName() + "完成作业用时:" + (end-start) + "h");
    }
}

⭐️ 测试类:


public class TestTemplate {
    public static void main(String[] args) {
        new Pupil().homework();  // 小学生
        new MStudent().homework();  // 中学生
        new CStudent().homework();  // 大学生
    }
}


🍎 实现结果:


小学生完成作业用时:1h

中学生完成作业用时:5h

大学生完成作业用时:26h


好啦,到这里我们已经实现了需求,但是,小伙伴们,有没有发现一个问题?我们来比较一下小学生、中学生、大学生三个类中的 homework() 方法就会发现: 代码的冗余度过高,在方法内有很多重复的步骤,代码的复用性不强! 怎么解决呢?别急继续往下看~


2 初步优化(每个类内部)

😦 我们可以从 homework() 方法中将重复的部分单独提出来,设置成一个 computingTime() 方法,用于计算作业完成所需要的时间,具体见下图(以大学生类为例,其他两个类进行一样的操作):


⭐️ Star 1: 将公共部分提取成一个方法


⭐️ Star 2: 其余部分在该方法中调用



🍌 优化后的代码如下:

public class TestTemplate {
    public static void main(String[] args) {
        new Pupil().computingTime();  // 小学生
        new MStudent().computingTime();  // 中学生
        new CStudent().computingTime();  // 大学生
    }
}
class Pupil{
    private String name = "小学生";
    public String getName(){
        return this.name;
    }
    // 计算作业完成所需要的时间
    public void computingTime(){
        long start = System.currentTimeMillis();
        homework(); // 写作业
        long end = System.currentTimeMillis();
        System.out.println(getName() + "完成作业用时:" + (end-start) + "h");
    }
    // 完成作业
    public void homework(){
        long time = 0;
        for (int i = 0; i < 100000; i++) {
            time += i;
        }
    }
}
class MStudent{
    private String name = "中学生";
    public String getName(){
        return this.name;
    }
    // 计算作业完成所需要的时间
    public void computingTime(){
        long start = System.currentTimeMillis();
        homework(); // 写作业
        long end = System.currentTimeMillis();
        System.out.println(getName() + "完成作业用时:" + (end-start) + "h");
    }
    // 完成作业
    public void homework(){
        long time = 0;
        for (int i = 0; i < 9000000; i++) {
            time += i;
        }
    }
}
class CStudent{
    private String name = "大学生";
    public String getName(){
        return this.name;
    }
    // 计算作业完成所需要的时间
    public void computingTime(){
        long start = System.currentTimeMillis();
        homework(); // 写作业
        long end = System.currentTimeMillis();
        System.out.println(getName() + "完成作业用时:" + (end-start) + "h");
    }
    // 完成作业
    public void homework(){
        long time = 0;
        for (int i = 0; i < 90000000; i++) {
            time += i;
        }
    }
}

🍑 现在,我们已经成功将方法中的公共部分给提取出来,单独设置成了 computingTime() 方法,但是,很快我们又发现了问题:一共有三个类,每个类都需要提取一次,设置出一个单独的方法,还是过于繁琐,需要进一步优化,我们接着往下看。


3 抽象模板设计

😎 既然重复,我们为何不 尝试将重复的部分提取到一个模板类里,让这三个类继承 呢?这样每个类都不需要声明该方法,就可以使用啦!具体如下图:


🍑 在这里,我们将三个类中共有的computingTime() 方法提取到 Template类作为模板,让子类继承。并且,将三个类中不同的部分 homework类 在父类中抽象,子类实现。在实际调用中,由于动态绑定机制,使用的则是 new 创建的对象所绑定的方法,先是子类,若子类不存在该方法再访问父类,这点在之前的文章讲过,这里直接上传送门哈!

❤️ 【JavaSE】面向对象之多态、向上转型与向下转型

具体方式如下:


🍌 优化后的完整代码:


public class TestTemplate {
    public static void main(String[] args) {
        new Pupil().computingTime();  // 小学生
        new MStudent().computingTime();  // 中学生
        new CStudent().computingTime();  // 大学生
    }
}
// 模板类
abstract class Template{
    private String name;
    public String getName(){
        return this.name;
    }
    // 计算作业完成所需要的时间
    public void computingTime(){
        long start = System.currentTimeMillis();
        homework(); // 写作业
        long end = System.currentTimeMillis();
        System.out.println(getName() + "完成作业用时:" + (end-start) + "h");
    }
    abstract void homework();
}
class Pupil extends Template{
    private String name = "小学生";
    public String getName(){
        return this.name;
    }
    // 完成作业
    public void homework(){
        long time = 0;
        for (int i = 0; i < 100000; i++) {
            time += i;
        }
    }
}
class MStudent extends Template{
    private String name = "中学生";
    public String getName(){
        return this.name;
    }
    // 完成作业
    public void homework(){
        long time = 0;
        for (int i = 0; i < 9000000; i++) {
            time += i;
        }
    }
}
class CStudent extends Template{
    private String name = "大学生";
    public String getName(){
        return this.name;
    }
    // 完成作业
    public void homework(){
        long time = 0;
        for (int i = 0; i < 90000000; i++) {
            time += i;
        }
    }
}

🍎 实现结果:


小学生完成作业用时:1h

中学生完成作业用时:4h

大学生完成作业用时:26h


相关文章
|
2天前
|
存储 Java
Dijkstra最短路径(Java)(详细+模板)
Dijkstra最短路径(Java)(详细+模板)
12 4
|
2天前
|
机器学习/深度学习 算法 Java
全排列(分治)(Java语言 +全排列模板)
全排列(分治)(Java语言 +全排列模板)
8 2
|
2天前
|
设计模式 Java
【JAVA基础篇教学】第十四篇:Java中设计模式
【JAVA基础篇教学】第十四篇:Java中设计模式
|
2天前
|
设计模式 算法 Java
设计模式在Java开发中的应用
设计模式在Java开发中的应用
18 0
|
2天前
|
传感器 人工智能 前端开发
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
智慧校园电子班牌,坐落于班级的门口,适合于各类型学校的场景应用,班级学校日常内容更新可由班级自行管理,也可由学校统一管理。让我们一起看看,电子班牌有哪些功能呢?
103 4
JAVA语言VUE2+Spring boot+MySQL开发的智慧校园系统源码(电子班牌可人脸识别)Saas 模式
|
2天前
|
设计模式 前端开发 Java
19:Web开发模式与MVC设计模式-Java Web
19:Web开发模式与MVC设计模式-Java Web
24 4
|
2天前
|
设计模式 存储 前端开发
18:JavaBean简介及其在表单处理与DAO设计模式中的应用-Java Web
18:JavaBean简介及其在表单处理与DAO设计模式中的应用-Java Web
26 4
|
2天前
|
设计模式 缓存 监控
JAVA设计模式之结构型模式
结构模型:适配器模型、桥接模型、过滤器模型、组合模型、装饰器模型、外观模型、享受元模型和代理模型。
22 3
|
2天前
|
设计模式 算法 Java
Java基础教程(19)-设计模式简述
【4月更文挑战第19天】设计模式是软件设计中反复使用的代码设计经验,旨在提升代码的可重用性、可扩展性和可维护性。23种模式分为创建型、结构型和行为型三类。创建型模式如工厂方法、抽象工厂、建造者、原型和单例,关注对象创建与使用的分离。结构型模式涉及对象组合,如适配器、装饰器、外观等,增强结构灵活性。行为型模式专注于对象间职责分配和算法合作,包括责任链、命令、观察者等。设计模式提供标准化解决方案,促进代码交流和复用。
|
2天前
|
Java 开发者 UED
Java 异步和事件驱动编程:探索响应式模式
【4月更文挑战第27天】在现代软件开发中,异步和事件驱动编程是提高应用性能和响应性的关键策略。Java 提供了多种机制来支持这些编程模式,使开发者能够构建高效、可扩展的应用程序。
31 4