抽象类、模板方法模式
抽象类概述
在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.打开虚拟机ÿ…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
