抽象类、模板方法模式
抽象类概述
在Java中abstract是抽象的意思,如果一个类中的某个方法的具体实现不能确定,就可以申明成abstract修饰的抽象方法(不能写方法体了),这个类必须用abstract修饰,被称为抽象类。
抽象方法定义:修饰符 abstract 返回值类型 方法名称(形参列表);,只有方法签名,没有方法体,使用了abstract修饰。
抽象类定义:修饰符 abstract class 类名{ }
抽象类可以理解成类的不完整设计图,是用来被子类继承的。
抽象类的作用: 可以被子类继承、充当模板的、同时也可以提高代码复用。
怎么理解模板?相当于以一篇缺少中间内容的作文作为模板,结构都不用变,我只要充实下中间的内容,那么子类以抽象类作为模板,只要实现下抽象方法即可。
示例:
public abstract class Animal {private String name;public abstract void run();public String getName() {return name;}public void setName(String name) {this.name = name;}
}
抽象类的案例
系统需求
某加油站推出了2种支付卡,一种是预存10000的金卡,后续加油享受8折优惠,另一种是预存5000的银卡 ,后续加油享受8.5折优惠。
请分别实现2种卡片进入收银系统后的逻辑,卡片需要包含主人名称,余额,支付功能。
分析实现
创建一张卡片父类:定义属性包括主人名称、余额、支付功能(具体实现交给子类)
创建一张白金卡类:重写支付功能,按照原价的8折计算输出。 创建一张银卡类:重写支付功能,按照原价的8.5折计算输出。
代码
/**抽象父类*/
public abstract class Card {private String name; // 主人名称private double money;/**子类一定要支付的,但是每个子类支付的情况不一样,所以父类把支付定义成抽象方法,交给具体子类实现*/public abstract void pay(double money);public String getName() {return name;}public void setName(String name) {this.name = name;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}
}
/**金卡*/
public class GoldCard extends Card{@Overridepublic void pay(double money) {// 优惠后的金额算出来:double rs = money * 0.8;double lastMoney = getMoney() - rs;System.out.println(getName() + "当前账户总金额:"+ getMoney() +",当前消费了:" + rs +",消费后余额剩余:" +lastMoney);setMoney(lastMoney); // 更新账户对象余额}
}
银卡差不多
抽象类的特征、注意事项
1、有得有失: 得到了抽象方法,失去了创建对象的能力。
2、抽象类为什么不能创建对象? 反证法。
3、类有的成员(成员变量、方法、构造器)抽象类都具备
4、抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
5、一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
6、不能用abstract修饰变量、代码块、构造器。
final和abstract是什么关系?
互斥关系
abstract定义的抽象类作为模板让子类继承,final定义的类不能被继承。
抽象方法定义通用功能让子类重写,final定义的方法子类不能重写。
抽象类的应用知识:模板方法模式
概述
模板方法模式(Template Method Pattern)是一种行为设计模式,它在一个方法中定义一个算法的骨架,允许子类在不改变算法结构的情况下重新定义某些步骤的具体内容。换句话说,模板方法模式封装了不变的部分,而将可变的部分留给子类来实现。
在模板方法模式中,通常有一个抽象类(或称为模板类),它定义了算法的骨架和步骤的顺序。这个抽象类还包含一些抽象方法或钩子方法(hook methods),这些方法是抽象的,需要在子类中具体实现。子类通过实现这些抽象方法,可以重新定义算法中的某些步骤,以满足特定的需求。
使用模板方法模式的好处有以下几点:
- 代码复用:模板方法模式将算法的不变部分封装在父类中,而可变部分则留给子类来实现。这样,子类可以在不改变算法结构的情况下,通过覆盖父类的方法来实现自己的逻辑,从而实现了代码的复用。
- 扩展性:由于算法的可变部分被抽象出来,子类可以通过扩展父类来实现新的功能。这符合开闭原则,即对扩展开放,对修改封闭。
- 控制子类行为:模板方法模式通过定义算法的骨架和步骤顺序,可以控制子类的行为。父类中的模板方法规定了算法的整体流程,而子类则通过实现抽象方法来参与这个流程。
然而,模板方法模式也有一些潜在的缺点:
- 类个数增加:对于每个不同的实现,都需要定义一个子类,这可能会导致类的个数增加,系统更加庞大和复杂。
- 反向控制结构:父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构。这可能会增加代码阅读的难度和维护的复杂性。
在实际应用中,模板方法模式通常用于实现一些具有固定流程的操作,如文件操作、数据库操作、网络通信等。在这些场景中,通过使用模板方法模式,可以将不变的部分封装起来,而将可变的部分留给子类来实现,从而提高代码的复用性和可维护性。
什么时候使用模板方法模式
使用场景说明:当系统中出现同一个功能多处在开发,而该功能中大部分代码是一样的,只有其中部分可能不同的时候。

模板方法模式实现步骤
把功能定义成一个所谓的模板方法,放在抽象类中,模板方法中只定义通用且能确定的代码。
模板方法中不能确定的功能定义成抽象方法让具体子类去实现。
案例:银行利息结算系统
需求:
某软件公司要为某银行的业务支撑系统开发一个利息结算系统,账户有活期和定期账户两种。
活期是0.35%,定期是 1.75%,定期如果满10万额外给予3%的收益。
结算利息要先进行用户名、密码验证,验证失败直接提示,登录成功进行结算。
分析:

实现步骤:
创建一个抽象的账户类Account作为父类模板,提供属性(卡号,余额)。
在父类Account中提供一个模板方法实现登录验证,利息结算、利息输出。
具体的利息结算定义成抽象方法,交给子类实现。
定义活期账户类,让子类重写实现具体的结算方法。
定义定期账户类,让子类重写实现具体的结算方法。
创建账户对象,完成相关功能。
代码:
public abstract class Account {private String cardId;private double money;public Account() {}public Account(String cardId, double money) {this.cardId = cardId;this.money = money;}/**模板方法*/public final void handle(String loginName , String passWord ){// a.判断登录是否成功if("itheima".equals(loginName) && "123456".equals(passWord)){System.out.println("登录成功。。");// b.正式结算利息// 当前模板方法知道所有子类账户都要结算利息,但是具体怎么结算,模板不清楚,交给具体的子类来计算double result = calc();// c.输出利息详情System.out.println("本账户利息是:"+ result);}else{System.out.println("用户名或者密码错误了");}}public abstract double calc();public String getCardId() {return cardId;}public void setCardId(String cardId) {this.cardId = cardId;}public double getMoney() {return money;}public void setMoney(double money) {this.money = money;}
}
/**活期账户*/
public class CurrentAccount extends Account {public CurrentAccount(String cardId, double money) {super(cardId, money);}@Overridepublic double calc() {// b.正式结算利息double result = getMoney() * 0.0175; // 结算利息了return result;}}
public class Test {public static void main(String[] args) {CurrentAccount acc = new CurrentAccount("ICBC-111", 100000);acc.handle("itheima", "123456");}
}
模板方法我们是建议使用final修饰的,这样会更专业,那么为什么呢?
答:模板方法是给子类直接使用的,不是让子类重写的, 一旦子类重写了模板方法就失效了。
模板方法模式解决了什么问题?
极大的提高了代码的复用性。
模板方法已经定义了通用结构,模板不能确定的定义成抽象方法。
使用者只需要关心自己需要实现的功能即可。
相关文章:
抽象类、模板方法模式
抽象类概述 在Java中abstract是抽象的意思,如果一个类中的某个方法的具体实现不能确定,就可以申明成abstract修饰的抽象方法(不能写方法体了),这个类必须用abstract修饰,被称为抽象类。 抽象方法定义&…...
消息队列kafka
消息队列解决的问题 1. 解耦,通过消息队列实现应用之间解耦,模块儿之间解耦 2. 跨线程/进程通信,通过消息队列传递数据,实现不同线程/进程间通信 3. 提升系统稳定性,在高并发场景通过消息队列缓冲,可以实…...
复盘成长——2024.2月复盘
复盘的目的和范围 每月一次的精心复盘,不仅是对自身工作成就、学习进步与成长轨迹的深度梳理,更是一种对未来路径的细致规划。通过这一过程,我期望能够更加精准地把握生活的节奏和职场的航向,从中汲取经验、聚焦目标,…...
Kafka安全模式之身份认证
一、简介 Kafka作为一个分布式的发布-订阅消息系统,在日常项目中被频繁使用,通常情况下无论是生产者还是消费者只要订阅Topic后,即可进行消息的发送和接收。而kafka在0.9.0.0版本后添加了身份认证和权限控制两种安全服务,本文主要…...
3、Redis-List【常用】
目录 一、重要特点 二、常用命令 三、Redis中List类型应用场景 一、重要特点 ①Redis中的List,视为双向链表 ②Redis中的List,数据可以重复 二、常用命令 常用命令 格式含义例子rpush key value从右边往key中添加value值rpush hobby java pythonlpu…...
黑马c++ STL部分 笔记(7) list容器
list基本概念 功能:将数据进行链式存储 链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的 链表的组成:链表由一系列结点组成结点的组成:一个是存储数据元素…...
关于使用Mxnet GPU版本运行DeepAR报错解决方案
1.引言 我们经常使用GPU来训练和部署神经网络,因为与CPU相比,它提供了更多的计算能力。在本教程中,我们将介绍如何将GPU与MXNet GluonTS一起使用。 首先,确保您的机器中至少有一个Nvidia GPU,并正确安装了CUDA以及CUDN…...
【STM32】江科大STM32学习笔记汇总(50)
00. 目录 文章目录 00. 目录01. STM32学习笔记汇总02. 相关资料下载03. 附录 01. STM32学习笔记汇总 【STM32】STM32学习笔记-课程简介(01) 【STM32】STM32学习笔记-STM32简介(02) 【STM32】STM32学习笔记-软件安装(03) 【STM32】STM32学习笔记-新建工程(04) 【STM32】STM…...
LabVIEW非接触式电阻抗层析成像系统
LabVIEW非接触式电阻抗层析成像系统 非接触式电阻抗层析成像(NEIT)技术以其无辐射、非接触、响应速度快的特点,为实时监测提供了新的解决方案。基于LabVIEW的电阻抗层析成像系统,实现了数据的在线采集及实时成像,提高…...
蓝桥杯备战刷题three(自用)
1.合法日期 #include <iostream> #include <map> #include <string> using namespace std; int main() {map<string,int>mp;int days[13]{0,31,28,31,30,31,30,31,31,30,31,30,31};for(int i1;i<12;i){for(int j1;j<days[i];j){string sto_strin…...
密码学——二次剩余
引言 二次剩余在许多密码学算法和数论问题中具有重要的作用,这个概念涉及到同余方程等概念。 同余 学习二次剩余的概念,首先要了解同余方程的概念,首先默认研究范围为整数,假设 f ( x ) f(x) f(x)是一个整系数多项式,我们讨论是否有整数值x满足同余式 f (...
10.7、华为数通HCIP-DataCom H12-821单选题:121-140
121、关于OSPF特性描述错误的是:D A、OSPF采用链路状态算法。 B、每个路由器通过泛洪 LSA 向外发布本地链路状态信息 C、每台 OSPF 设备都会收集其它路由器发来的LSA 所有的LSA 放在一起便组成了链路状态数据库LSDB, D、OSPF 区域0中所有路由器的 LSDB 都相同。 E、每台…...
多租户篇 | MatrixOne与MySQL全面对比
MySQL 是经典的关系型数据库管理系统,以其简单易用的特性在中小型业务系统中广受开发人员的喜爱。但是MySQL的架构也具有一定的局限性,在需要具备"隔离性"的业务,例如 SaaS 系统或微服务架构等对"数据隔离"及"资源隔…...
python Matplotlib Tkinter-->导出pdf报表
环境 python:python-3.12.0-amd64 包: matplotlib 3.8.2 reportlab 4.0.9 import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk import tkinter as tk import tkinter.messagebox as messagebox impor…...
react-组件基础
1.目标 能够使用函数创建组件 能够使用class创建组件 能够给React元素绑定事件 能够使用state和setState() 能够处理事件中的this指向问题 能够使用受控组件方式处理表单 2.目录 React组件介绍 React组件的两种创建方式 React事件处理 有状态组件和无状态组件 组件中的state…...
The authenticity of host ‘github.com (20.205.243.166)‘ can‘t be established.
1、运行git clone报错: The authenticity of host github.com (20.205.243.166) cant be established. ECDSA key fingerprint is SHA256:p2QAC1TJYererOttrVc98/R1BWERWu3/LiyFdHfQM. Are you sure you want to continue connecting (yes/no/[fingerprint])? 这个…...
arduino uno R3驱动直流减速电机(蓝牙控制)
此篇博客用于记录使用arduino驱动直流减速电机的过程,仅实现简单的功能:PID调速、蓝牙控制 1、直流减速电机简介2、DRV8833电机驱动模块简介3、HC-05蓝牙模块简介电机转动测试4、PID控制5、蓝牙控制电机 1、直流减速电机简介 我在淘宝购买的电机&#x…...
智能家居控制系统(51单片机)
smart_home_control_system 51单片机课设,智能家居控制系统 使用及转载请标明出处(最好点个赞及star哈哈) Github地址,带有PPT及流程图 Gitee码云地址,带有PPT及流程图 以STC89C52为主控芯片,以矩阵键…...
软考高级系统分析师之 URL 知识点和例题
一、AI 解读 URL(统一资源定位器)的结构是网络上定位资源的一种方式。一个典型的URL由几个部分组成: 协议(Scheme): 定义了用于访问资源的协议类型,如http、https、ftp等。例如,在 http://www.…...
vmware虚拟机centos中/dev/cl_server8/root 空间不够
在使用vmware时发现自己的虚拟机的/dev/cl_server8/root空间不够了,没办法安装新的服务。所以查了一下改空间的办法。 1.在虚拟机关闭的状态下,选中需要扩容的虚拟机->设置->硬件-> 硬盘->扩展->填写扩大到的值。 2.打开虚拟机ÿ…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...
基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
