java中的抽象类到底如何用

抽象类的使用

  • 一、设计模式中的使用
    • 1. 模板方法模式
    • 2. 抽象工厂模式
  • 二、扩展性和灵活性
  • 三、为什么开发时抽象类用的很少,反而用接口的很多

一、设计模式中的使用

1. 模板方法模式

1.定义:当你需要为一组相关类提供一个操作的框架,其中一些步骤是固定的,而其他步骤(由抽象方法表示)则在子类中实现。例如,制定一个学习计划,其中学习计划的基本流程是固定的(比如先预习、再上课、最后复习),但是每一步的具体实现可能因学生类型而异。

2.结构

  • 抽象类:定义并实现一个模板方法,该方法定义了算法的骨架,并调用一些抽象方法,这些抽象方法由子类实现。
  • 具体子类:实现抽象类中声明的抽象方法,完成具体的步骤。

3.代码

定义一个抽象类


/*** 抽象类:学习计划模板*/
public abstract class StudyPlan {// 模板方法,定义学习流程的骨架public final void studyProcess(String name) {preview(name);attendClass(name);review(name);}// 预习protected abstract void preview(String name);// 上课protected abstract void attendClass(String name);// 复习protected abstract void review(String name);
}

中学生学习计划子类的实现

/*** 中学生学习计划*/
public class MiddleStudentStudyPlan extends StudyPlan {@Overrideprotected void preview(String name) {System.out.println(name + ":预习");}@Overrideprotected void attendClass(String name) {System.out.println(name + ":上课");}@Overrideprotected void review(String name) {System.out.println(name + ":复习");}
}

小学生学习计划子类的实现

/*** 小学生学习计划*/
public class PrimaryStudentStudyPlan extends StudyPlan {@Overrideprotected void preview(String name) {System.out.println(name + ":预习");}@Overrideprotected void attendClass(String name) {System.out.println(name + ":上课");}@Overrideprotected void review(String name) {System.out.println(name + ":复习");}}

测试

public class TestMoBan {public static void main(String[] args) {// 小学生的学习计划new PrimaryStudentStudyPlan().studyProcess("小学生");// 中学生的学习计划new MiddleStudentStudyPlan().studyProcess("中学生");}
}

2. 抽象工厂模式

1.什么是抽象工厂模式 : 它提供了一种方式来创建一系列相关的或相互依赖的对象,而无需指定它们具体的类。这种模式允许客户端使用抽象接口来操作对象,而不需要了解具体类的实现细节,从而使得系统在不修改具体类的情况下引入新产品族变得容易。

2.结构

  • 抽象工厂:声明一个创建一系列相关或相互依赖对象的接口,而不需要指定它们具体的类。
  • 具体工厂:实现抽象工厂接口,负责创建一个产品系列的具体对象。
  • 抽象产品:定义一组产品的接口,使得在各个具体产品之间可以互换。
  • 具体产品:实现抽象产品接口的具体类,每个具体工厂都创建一个具体产品的实例。

3.优点

  • 将产品的创建和使用分离开来,使得客户端代码更加简洁,并且向客户端隐藏产品的创建细节。
  • 将一系列相关的产品对象的创建工作统一到一个抽象工厂中,客户端只需要访问抽象工厂即可,具 体的产品工厂可以灵活替换。
  • 当一个族中的多个对象被设计成一起工作时, 它能够保证客户端始终只使用同一个族中的对象。

4.缺点

  • 一个产品族下增加新的产品等级非常困难,甚至需要修改抽象层代码和其下所有的实现, 严重违背了“开闭原则”。
  • 增加了代码的复杂性,增加了系统的抽象性,增加了理解难度

5.实现方式太麻烦了,这里就不演示代码了,有兴趣的博主可以自行百度。

二、扩展性和灵活性

1.设定接口规范:抽象类可以定义一组抽象方法,这些方法没有具体实现,要求所有子类必须实现这些方法。这实际上是在设定一个接口规范,确保所有子类都遵循相同的操作接口,即使它们的具体实现可能不同。这提高了系统的规范性和一致性。

2.提供默认实现:除了抽象方法外,抽象类还可以包含具体方法,为子类提供默认行为的实现。这意味着子类可以重用这些实现,或者覆盖它们以提供定制化的功能。这种机制既减少了代码重复,又增加了灵活性,因为子类可以选择性地覆盖或扩展父类的行为。

3.支持多态性:通过抽象类,可以利用多态性原则,编写与具体实现分离的代码。这意味着你可以针对抽象基类编程,而不用担心具体子类的细节。这样,当需要引入新的子类或修改现有子类的实现时,只需保持对外接口不变,即可轻松替换或扩展功能,而不影响到调用这些抽象类的地方。

4.代码组织和模块化 :抽象类有助于将相关的功能组织在一起,形成逻辑上的模块。每个抽象类可以代表一个概念或功能领域,它的子类则代表这个领域内的具体变体。这种组织方式使得代码结构清晰,易于理解和维护,同时也便于团队协作开发。

5.易于扩展:随着项目的发展,需求可能会变化,需要添加新的功能。抽象类作为基础框架,允许你在不破坏原有代码结构的基础上,通过添加新的子类来扩展功能。这种设计模式使得系统更加灵活,能够更好地适应未来的变化。

6.演示

  1. 创建一个抽象工厂
public abstract class DbConnectionFactory {// 打开链接public abstract void openConnection(String name);// 关闭链接public abstract void closeConnection(String name);}
  1. 创建MySQL连接
public class MySQLConnection extends DbConnectionFactory {@Overridepublic void openConnection(String name) {System.out.println(name + ": 打开了MySQL连接");}@Overridepublic void closeConnection(String name) {System.out.println(name + ": 关闭了MySQL连接");}
}
  1. 创建PgSQL连接
public class PgSQLConnection extends DbConnectionFactory {@Overridepublic void openConnection(String name) {System.out.println(name + ":打开了PgSQL连接");}@Overridepublic void closeConnection(String name) {System.out.println(name + ":关闭了PgSQL连接");}
}
  1. 测试
public class TestMain {public static void main(String[] args) {DbConnectionFactory mySQLConnection = new MySQLConnection();mySQLConnection.openConnection("用户A");mySQLConnection.closeConnection("用户A");PgSQLConnection pgSQLConnection = new PgSQLConnection();pgSQLConnection.openConnection("用户B");pgSQLConnection.closeConnection("用户B");}
}

三、为什么开发时抽象类用的很少,反而用接口的很多

1.多重继承限制:Java中类只允许单一继承,这意味着一个类只能继承一个抽象类。然而,一个类却可以实现多个接口,这为多继承提供了替代方案,增加了设计的灵活性。因此,当需要实现多个行为规范时,接口成为更自然的选择。

2.多重继承限制:Java中类只允许单一继承,这意味着一个类只能继承一个抽象类。然而,一个类却可以实现多个接口,这为多继承提供了替代方案,增加了设计的灵活性。因此,当需要实现多个行为规范时,接口成为更自然的选择。

3.接口的进化:自从Java 8引入默认方法和静态方法以来,接口变得更加灵活。默认方法允许在接口中提供实现,这样就能够在不破坏现有实现的情况下向接口添加新功能,这在一定程度上弥补了接口与抽象类之间功能上的差距。

4.设计原则:面向接口编程鼓励针对接口而非实现编程,这有利于降低耦合度,提高代码的可测试性和可维护性。接口更纯粹地体现了这一原则,因为它不包含任何状态或具体实现,强调的是行为的约定而非实现细节。

5.框架和库的偏好:现代框架和库,如Spring框架,倾向于使用接口来进行依赖注入,以利用其提供的灵活性和可配置性。这种设计模式鼓励使用接口来定义组件之间的合同。

6.清晰的职责划分:接口通常用于定义类型或行为的契约,而抽象类可能包含更多关于实现细节的逻辑。使用接口可以帮助开发者更清晰地分离关注点,使得代码更容易理解和维护。:自从Java 8引入默认方法和静态方法以来,接口变得更加灵活。默认方法允许在接口中提供实现,这样就能够在不破坏现有实现的情况下向接口添加新功能,这在一定程度上弥补了接口与抽象类之间功能上的差距。

7.设计原则:面向接口编程鼓励针对接口而非实现编程,这有利于降低耦合度,提高代码的可测试性和可维护性。接口更纯粹地体现了这一原则,因为它不包含任何状态或具体实现,强调的是行为的约定而非实现细节。

8.框架和库的偏好:现代框架和库,如Spring框架,倾向于使用接口来进行依赖注入,以利用其提供的灵活性和可配置性。这种设计模式鼓励使用接口来定义组件之间的合同。

9.清晰的职责划分:接口通常用于定义类型或行为的契约,而抽象类可能包含更多关于实现细节的逻辑。使用接口可以帮助开发者更清晰地分离关注点,使得代码更容易理解和维护。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/13793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Muduo】三大核心之EventLoop

Muduo网络库的EventLoop模块是网络编程框架中的核心组件,负责事件循环的驱动和管理。以下是对EventLoop模块的详细介绍: 作用与功能: EventLoop是网络服务器中负责循环的重要模块,它持续地监听、获取和处理各种事件,…

10个最佳Android数据恢复工具,用于恢复已删除的文件

由于我们现在在智能手机上存储了许多重要文件,因此了解数据恢复工具变得很重要。您永远不会知道何时需要使用适用于Android的数据恢复工具。 由于不乏Windows数据恢复工具,因此从崩溃的计算机中恢复文件很容易。但是,当涉及到从Android恢复数…

兆原数通基于Apache SeaTunnel的探索实践

随着大数据技术的不断发展,数据同步工具在企业中的应用变得愈发重要。为了满足复杂多样的业务需求,找到一款高效、灵活的数据同步工具变得尤为关键。 在这篇文章中,我们将分享兆原数通研发经理李洪军对Apache SeaTunnel的选择、应用及经验。这…

jinkens打包前端依赖下载失败怎么办

不知道有没有小伙伴遇见这种问题,项目在本地可以正常下载、运行打包,但在jinkens上就不行了,配置了几种镜像也还是不行,这要如何解决呢? 那就只能去到jinkens配置的工作空间那里,找到对应的项目 &#xff…

Django使用Celery实现异步和定时任务功能

1、装库 celery==4.4.2 django-celery-beat==2.2.0 django-celery-results==2.0.12、添加应用 安装完依赖之后,把上面的两个应用添加到Django配置文件settings.py的INSTALLED_APPS里面: 添加celery配置信息 在项目的配置文件中添加如下配置信息,具体的配置作用见注释 I…

YOLOv5/v7 应用轻量级通用上采样算子CARAFE

1. 介绍 CARAFE(Content-Aware ReAssembly of FEatures)是一种轻量级的通用上采样算子,它可以用于提高卷积神经网络(CNN)中特征图的分辨率。CARAFE 的特点是计算量小、参数少、易于实现,因此非常适合用于移…

开放重定向漏洞

开放重定向漏洞 1.开放重定向漏洞概述2.攻击场景:开放重定向上传 svg 文件3.常见的注入参数 1.开放重定向漏洞概述 开放重定向漏洞(Open Redirect)是指Web应用程序接受用户提供的输入(通常是URL参数),并将…

代码随想录算法训练营第四十五天|139.单词拆分

139.单词拆分 这题首先肯定是排序问题而不是组合问题,因为单词的顺序是一定的,所以组成单词的字符串顺序也是一定的。所以应该先循环背包容量,再循环物品个数。 背包容量就是s字符串,物品就是数组中的单词,字符串的循…

Kubernetes 文档 / 概念 / 工作负载 / Pod / Init 容器

Kubernetes 文档 / 概念 / 工作负载 / Pod / Init 容器 此文档从 Kubernetes 官网摘录 中文地址 英文地址 本页提供了 Init 容器的概览。Init 容器是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本。…

总结优秀的prompt案例,学习更有效的prompt提示词工程写法,值得收藏

Prompt 提示词工程大多数人都在用,而且都会用,但是不一定写的好?很多人都在想怎么写好,更能满足自己的业务需求,或者实际场景。 我最近工作中也写了很多的prompt,像zero-shot、few-shot、COT这些都尝试过、…

FSC认证是什么?森林认证的好处是什么?

FSC认证(Forest Stewardship Council,森林管理委员会认证)是一种运用市场机制来促进森林可持续经营,实现生态、社会和经济目标的工具。以下是关于FSC认证的详细介绍: 一、FSC认证包括两个方面: 森林经营认…

乡村振兴与农业现代化:以现代农业科技为引领,提升农业综合生产能力,打造高产高效、生态安全的美丽乡村

目录 一、引言 二、现代农业科技在乡村振兴中的作用 (一)提高农业生产效率 (二)促进农业产业升级 (三)改善农村生态环境 三、提升农业综合生产能力的途径 (一)加强农业科技研…

spring中依赖注入(DI)是什么?

好的,让我以尽可能通俗易懂的方式来解释什么是依赖注入(DI,Dependency Injection)。 假设你正在制作一款游戏,游戏中有个角色需要使用武器。在没有依赖注入的情况下,这个角色可能需要自己创建一个武器。这…

计算理论基础:4、复杂性理论

复杂性理论 c e n t e r p r o b l e m : P ≠ N P center\ \ problem:P \ne NP center problem:PNP 1.P、EXP、NP 定义1 D T I M E DTIME DTIME ​ T : N → N T:\N\rightarrow \N T:N→N,语言 L ∈ D T I M E ( T ( n ) ) L\in DTIME(T(n)) L∈DTIME(T(n)),当且仅当存…

Diffusion Policy:基于扩散模型的机器人动作生成策略

项目地址: Diffusion Policy (columbia.edu) 一、摘要 本文介绍了 "扩散策略",这是一种生成机器人行为的新方法,它将机器人的视觉运动策略(visuomotor policy)表示为条件去噪扩散过程(conditi…

添加、修改和删除列表元素

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 添加、修改和删除列表元素也称为更新列表。在实际开发时,经常需要对列表进行更新。下面我们介绍如何实现列表元素的添加、修改和删除。 …

TypeScript进阶 类型演算与高级内置类型

简介: TypeScript 是一种静态类型检查的 JavaScript 超集,它通过类型注解和类型推断来提供更强大的类型系统。在 TypeScript 中,类型演算是一种重要的概念,它允许我们在编译时对类型进行操作和计算。本文将深入探讨 TypeScript 类…

如何使用Matlab进行三角剖分(自定义函数实现delaunayTriangulation 使用Bowyer-Watson 算法)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、Delaunay三角形 二、使用步骤 1.Bowyer-Watson算法 2.算法步骤 三、动画演示 四、核心代码 五、对比matlab自带函数和我们的算法: 总结 前…

谷歌开源项目BERT源码解读与应用实例

数据及代码见文末 基于BERT的中文情感分析实战:基于BERT的中文情感分析实战-CSDN博客 基于BERT的中文命名实体识别识别实战:基于BERT的中文命名实体识别识别实战-CSDN博客 1.项目配置文件 GLUE/BERT_BASE_DIR是项目的预训练权重,预训练权重主要包含3个部分:参数配置文件…

打气球小游戏

1.气球往上飘 我们声明两个符号常量来作为窗体的长和宽,接着就是常规操作 #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600#include<easyx.h> #include<stdio.h> int main() {initgraph(WINDOW_WIDTH, WINDOW_HEIGHT);setbkcolor(WHITE);cleardevice();get…