【️接口和抽象类的区别,如何选择?】

在这里插入图片描述

✅接口和抽象类的区别,如何选择?

  • ✅ 接口和抽象类的区别
      • ✅方法定义
      • ✅修饰符
      • ✅构造器
      • ✅继承和实现
      • ✅单继承 、 多实现
      • ✅职责不同
  • ✅什么是模板方法模式,有哪些应用呢?
    • ✅典型理解
      • ✅示例
      • 💡思考
  • ✅你在工作中是如何使用设计模式的?

✅ 接口和抽象类的区别

接口和抽象类的区别其实挺多的。比如以下这些:

✅方法定义

接口和抽象类,最明显的区别就是接口只定义了一些方法而已,再不考虑Java 8 中的default方法情况下,接口中只有抽象方法,是没有实现的代码的。(Java 8 中可以有默认方法)

✅修饰符

抽象类中的抽象方法可以有publicprotected 、 和default 这些修饰符,而接口中默认修饰符是public。不可以使用其他修饰符。

✅构造器

抽象类可以有构造器,接口不能有构造器。

✅继承和实现

接口可以被实现,抽象类可以被继承。

✅单继承 、 多实现

一个类可以实现多个接口,但只能继承一个抽象类。接口支持多重继承,即一个接口可以继承多个其它接口。

public interface HollisTestService extends InitializingBean,DisposableBean {}

✅职责不同

接口和抽象类的职责不一样。接口主要用于制定规范,因为我们提倡也经常使用的都是面向接口棉城。而抽象类主要目的是为了复用,比较典型的就是模板方法模式。

了解完这些,我们使用Java代码来规整一下:

// 定义一个接口,名为Animal  
interface Animal {  // 定义一个抽象方法,用于发出动物的叫声  void makeSound();  
}  // 定义一个接口,名为Mammal  
interface Mammal extends Animal {  // 定义一个抽象方法,用于哺乳动物生育  public abstract void giveBirth();  
}  // 定义一个抽象类,名为Reptile  
abstract class Reptile implements Animal {  // 定义一个抽象方法,用于爬行动物移动  public abstract void move();  
}  // 定义一个实现了Mammal接口的类,名为Dog  
class Dog implements Mammal {  // 重写makeSound方法,实现狗的叫声  @Override  public void makeSound() {  System.out.println("汪汪!");  }  // 重写giveBirth方法,实现狗的生育行为(这里只是模拟,实际狗的生育行为更复杂)  @Override  public void giveBirth() {  System.out.println("汪汪!");  }  
}  // 定义一个继承了Reptile抽象类的类,名为Snake  
class Snake extends Reptile {  // 重写move方法,实现蛇的移动方式(这里只是模拟,实际蛇的移动方式更复杂)  @Override  public void move() {  System.out.println("蜿蜒爬行...");  }  
}  // 定义一个实现了Animal接口的类,名为Cat  
class Cat implements Animal {  // 重写makeSound方法,实现猫的叫声  @Override  public void makeSound() {  System.out.println("喵喵!");  }  
}  // 主函数,测试代码  
public class Main {  public static void main(String[] args) {  // 创建Dog对象并调用makeSound和giveBirth方法  Dog dog = new Dog();  dog.makeSound(); // 输出 "汪汪!"  dog.giveBirth(); // 输出 "汪汪!"  // 创建Snake对象并调用move方法  Snake snake = new Snake();  snake.move(); // 输出 "蜿蜒爬行..."  // 创建Cat对象并调用makeSound方法(注意Cat没有实现giveBirth方法)  Cat cat = new Cat();  cat.makeSound(); // 输出 "喵喵!"  }  
}

以上演示了接口和抽象类的复杂使用。Animal接口定义了一个makeSound方法,而Mammal接口继承了Animal接口并定义了一个giveBirth方法。Reptile抽象类实现了Animal接口并定义了一个move方法。Dog类实现了Mammal接口,而Snake类继承了Reptile抽象类。在主函数中,我们创建了Dog、Snake和Cat对象,并调用了它们的方法。这个例子展示了多个接口和抽象类的组合使用。


所以,当我们想要定义标准、规范的时间,就是用接口。当我们想要复用代码的时候,就使用抽象类。

一般实际开发中,我们会先把接口暴露给外部,然后业务代码中实现接口。如果多个实现类中有相同可复用的代码,则在接口和实现类中加一层抽象类,将公用部分代码抽出到抽象类中。可以参考一下模板方法模式,这是一个很好理解接口、抽象类和实现类之间关系的设计模式。

✅什么是模板方法模式,有哪些应用呢?

✅典型理解

模板方法模式是一种行为设计模式,他的主要作用就是复用代码。在很多时候,我们的代码中可能会有一些公共的部分并且还有一些定制的部分,那么公共这部分就可以定义在一个父类中,然后将定制的部分实现在子类中。这样了类可以根据需要扩展或重写父类的方法,而不需要改变算法的结构。

我们通常会把模板方法模式和策略模式一起使用,因为当我们使用策略模式的时候,会把具体的策略实现在策略服务里面,但是还剩下一些通用的逻辑,就可以通过模板方法模式进行复用。

✅示例

我们拿一个常见的优惠券作为示例,假设我们需要定义一个优惠券的申请服务。

abstract class Coupon {// 模板方法,定义优惠券的应用流程public final oid applyCoupon() {if (isCouponValid()) {if (isEligibleForDiscount()) {applyDiscount();}displayConfirmation();} else {displayInvalidCouponMessage();}}// 具体方法,用于判断优惠券是否有效protected boolean isCouponValid() {// 具体的判断逻辑,子类可以重写该方法来实现特定的有效性判断return true;}//具体方法,用于判断用户是否符合优惠券的折扣条件protected boolean isEligibleForDiscount() {//具体的判断逻辑,子类可以重写该方法来实现特定的条件判断return true;}//具体方法,用于判断用户是否符合优惠券的折扣条件protected boolean isEligibleForDiscount() {//具体的判断逻辑,子类可以重写该方法来实现特定的条件判断return true;}//抽象方法,由子类实现具体的优惠券折扣逻辑protected abstract void applyDiscount();// 抽象方法,由子类实现具体的优惠券确认展示逻辑protected abstract void displayConfirmation();// 具体方法,用于展示无效优惠券的信息protected void displayInvalidCouponMessage() {System.out.printIn("无效优惠券!);}
}

以上是一个抽象类。这个类中有一个具体的方法applyCoupon,其中定义了一个优惠券申请的具体实现,并且编排了多个其他的方法。

这就是一个典型的模板方法。我们可以基于这个抽象类来定义具体的实现:

class PercentageCoupon extends Coupon {@Overrideprotected void applyDiscount() {// 具体的百分比折扣逻辑System.out.printIn("应用百分比折扣优惠!);}@Overrideprotected void displayConfirmation() {// 具体的百分比优惠券确认展示逻辑System.out.printIn("百分比折扣优惠确认!");}
}class FixedAmountCoupon extends Coupon {@Overrideprotected void applyDiscount() {// 具体的固定金额折扣逻辑System.out.println("应用固定金额优惠!);}@Overrideprotected void displayConfirmation() {// 具体的固定金额优惠券确认展示逻辑System.out.printIn("固定金额优惠确认!");}
}

以上就是两个具体的实现,分别继承Coupon抽象类,并且实现其中的部分方法就可以了。

这样我们在实际使用时,可以直接使用FixedAmountCoupon 和 PercentageCoupon 类,并且直接调用它的applyCoupon方法就行了,如:

public class Main {public static void main(String[] args) {Coupon percentageCoupon = new PercentageCoupon();percentageCoupon.applyCoupon();System.out.println("-------------------------");Coupon fixedAmountCoupon = new FixedAmountCoupon();fixedAmountCoupon.applyCoupon();}
}

💡思考

看到这里,模板方法已经告一段落了,我们思考一下,如果在面试过程中,我们奇葩面试官问:你在**工作中是如何使用设计模式的?**那我们思考一下,脑子有思路吗?

没有思路也没关系!我们见招拆招,我给大家聊一下!

✅你在工作中是如何使用设计模式的?

工作中常用的设计模式有很多,如单例、工厂、策略、模板等。一般在工作中,是可以把策略、工厂和模板一起结合着来使用的

当我们需要有多个具体的策略服务的时候,那不同的内容放到策略服务中,那些公共的东西就可以抽象出来放到模板方法中了。那这些策略服务该如何管理呢?什么时候用什么策略服务呢?这时候就可以借助工广来管理这些服务。

如以下例子,我们需要定义一个支付服务,里面有一个支付方法:

public interface Payservice {public void pay(PayRequest payRequest);}class PayRequest {}

这是一个单独的接口,只定义了一个方法,那么我们再把所有支付渠道中公共的代码抽取出来,定义一个抽象类:

public abstract class AbstractPayService implements PayService {@Overridepublic void pay(PayRequest payRequest) {//前置检查validateRequest(payRequest);//支付核心逻辑doPay(payRequest);//后置处理postPay(payRequest);}	public abstract void doPay(PayRequest payRequest);private void postPay(PayRequest payRequest) {//支付成功的后置处理}public void validateRequest(PayRequest payRequest) {//参数检查}
}

这个抽象类中首先把pav方法给实现了,然后编排了几个其他的方法,这些公共的方法在抽象类中直接实现了,具体的支付核心实现,留给实现类去实现就行了。

然后我们就可以定义多个策略服务了:

@Service
public class AlipayPayService extends AbstractPayService {@Overridepublic void doPay(PayRequest payRequest) {//支付宝支付逻辑}
}@Service
public class WechatPayService extends AbstractPayService {@Overridepublic void doPay(PayRequest payRequest) {//微信支付逻辑}
}

这些服务协议定好了以后,需要一个地方统一管理,那就定义一个工厂吧:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class PayServiceFactory {@Autowiredpublic Map<String,ayService> payServiceMap = new ConcurrentHashMap<>();public PaySerice getPayService(String payChannel) {// alipay -> alipayPayService// wechat -> wechatPayServicereturn payServiceMap.get(payChannel +"PayService");}
}

在工厂中,把PayService的所有实现全部都注入到payServiceMap中,然后再需要用的是,直接调他的getPayService方法就行了


这样,在使用的时候,只需要通过工厂就能获取对应的策略服务进行服务调用了:

public class PayDomainService {@AutowiredPayServiceFactory payServiceFactory;public void pay(PayRequest payRequest) {String payChannel = payRequest.getPayChannel();payServiceFactory.getPayService(payChannel).pay(payRequest);}
}

以上,我们借助了Spring,结合了策略、模板以及工厂,实现了我们想要的功能,通过多种设计模式,减少重复代码,提升可维护性,也让代码更容易阅读和理解。

接博主上一篇博文: 如何理解面向对象和面向过程

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

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

相关文章

基于Java+Swingt学生信息管理系统

基于JavaSwing学生信息管理系统 一、系统介绍二、功能展示四、其他系统实现五、获取源码 一、系统介绍 1.用户登陆&#xff1a;在帮助按钮处&#xff0c;可以查看登陆账号及密码&#xff1a; 账号admin,密码123456 在未输入的情况下&#xff0c;会提示用户名不能为空&#xff…

设计模式——代理模式(结构型)

引言 代理模式是一种结构型设计模式&#xff0c; 让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问&#xff0c; 并允许在将请求提交给对象前后进行一些处理。 问题 为什么要控制对于某个对象的访问呢&#xff1f; 举个例子&#xff1a; 有这样一个消耗大量…

为什么选择计算机?大数据时代学习计算机的价值探讨

还记得当初自己为什么选择计算机? 计算机是在90年代兴起的专业,那时候的年轻人有驾照、懂外语、懂计算机是很时髦的事情! 当初你问我为什么选择计算机,我笑着回答:“因为我梦想成为神奇的码农!我想像编织魔法一样编写程序,创造出炫酷的虚拟世界!”谁知道,我刚入门的…

java内置的数据结构

Java语言提供了许多内置的数据结构&#xff0c;包括&#xff1a; 1. 数组&#xff08;Array&#xff09;&#xff1a;数组是最基本的数据结构之一&#xff0c;它是一个有序的元素集合&#xff0c;每个元素都有一个对应的索引。在Java中&#xff0c;数组可以通过声明和初始化来创…

stm32F4——蜂鸣器与按键的实例使用

stm32F4——蜂鸣器与按键的实例使用 蜂鸣器和按键的实质都是GPIO的使用&#xff0c;所以基本原理就不介绍啦&#xff0c;基本寄存器其实都是GPIO的高低电平的赋值&#xff0c;可以参考stm32——LEDGPIO的详细介绍 使用的开发板是华清远见的stm32F407VET6&#xff0c;都是M4的内…

AtCoder Beginner Contest 332 G. Not Too Many Balls(最大流转最小割 dp)

题目 n(n<500)种球&#xff0c;第i种有ai(0<ai<1e12)个球&#xff0c; m(m<5e5)个盒子&#xff0c;第j个能放bj(0<bj<1e12)个球 特别地&#xff0c;第j个盒子最多能放i*j个第i种球 求m个盒子能放的最多的球的总数 思路来源 官方题解 题解 显然是一个最…

STM32——时钟树与滴答计时器

STM32——时钟树与滴答计时器 使用的开发板为stm32F407VET6的芯片,主要介绍stm32的时钟树与滴答计时器的一些理论和一个自己编写的delay函数。 时钟树的结构图可以在STM32F4xx中文参考手册.pdf中的时钟这块找到。而滴答计时器是内核资源&#xff0c;需要到Cortex M3与M4权威指南…

链路聚合 (hcia)

原理 采用链路聚合技术可以在不进行硬件升级的条件下&#xff0c;通过将多个物理接口捆绑为一个逻辑接 口&#xff0c;达到增加链路带宽的目的。在实现增大带宽目的的同时&#xff0c;链路聚合采用备份链路的机制&#xff0c; 可以有效的提高设备之间链路的可靠性 &#x…

Error message “error:0308010C:digital envelope routines::unsupported“ 解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

Java_Lambda表达式JDK8新特性(方法引用)

一、Lambda表达式 接下来&#xff0c;我们学习一个JDK8新增的一种语法形式&#xff0c;叫做Lambda表达式。作用&#xff1a;用于简化匿名内部类代码的书写。 1.1 Lambda表达式基本使用 怎么去简化呢&#xff1f;Lamdba是有特有的格式的&#xff0c;按照下面的格式来编写Lamd…

认识loader和plugin

在 webpack 中&#xff0c;专注于处理 webpack 在编译过程中的某个特定的任务的功能模块&#xff0c;可以称为插件。它和 loader 有以下区别&#xff1a; 1loader 是一个转换器&#xff0c;将 A 文件进行编译成 B 文件&#xff0c;比如&#xff1a;将 A.less 转换为 A.css&…

2019年第八届数学建模国际赛小美赛A题放射性产生的热量解题全过程文档及程序

2019年第八届数学建模国际赛小美赛 A题 放射性产生的热量 原题再现&#xff1a; 假设我们把一块半衰期很长的放射性物质做成一个特定的形状。在这种材料中&#xff0c;原子核在衰变时会以随机的方向释放质子。我们假设携带质子的能量是一个常数。质子在穿过致密物质时&#x…

关于脑区的划分方法及一些模板说明

关于脑区的划分方法及一些模板说明 前言脑区划分方法的种类一些标准的脑区划分模板参考文献 前言 原创文章&#xff0c;未经同意请勿转载 Status: Completed Author: xioabai_Ry Time to Note: March 23, 2022 这里主要记录之前自己调研的有关脑区的划分方法及一些标准的脑区…

Web前端-HTML(表格与表单)

文章目录 1.表格与表单1.1 概述 2.表格 table2.1 表格概述2.2. 创建表格2.3 表格属性2.4. 表头单元格标签th2.5 表格标题caption&#xff08;了解&#xff09;2.6 合并单元格(难点)2.7 总结表格 3. 表单标签(重点)3.1 概述3.2 form表单3.3 input 控件(重点)type 属性value属性值…

机器学习算法---聚类

类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统计学检验箱…

【Redis】AOF 基础

因为 Redis AOF 的实现有些绕, 就分成 2 篇进行分析, 本篇主要是介绍一下 AOF 的一些特性和依赖的其他函数的逻辑,为下一篇 (Redis AOF 源码) 源码分析做一些铺垫。 AOF 全称: Append Only File, 是 Redis 提供了一种数据保存模式, Redis 默认不开启。 AOF 采用日志的形式来记…

写好ChatGPT提示词原则之:清晰且具体(clear specific)

ChatGPT 的优势在于它允许用户跨越机器学习和深度学习的复杂门槛&#xff0c;直接利用已经训练好的模型。然而&#xff0c;即便是这些先进的大型语言模型也面临着上下文理解和模型固有局限性的挑战。为了最大化这些大型语言模型&#xff08;LLM&#xff09;的潜力&#xff0c;关…

.NET core 搭建一个跨平台的 Web Service

以前搭建的webservice 都是基于.NET fromwork的&#xff0c;我们知道.NET fromwork是非跨平台的&#xff0c;只能部署在iis上&#xff0c;今天教大家用.NET core搭建一个可跨平台的Web Service 新建一个.net core空项目 给项目起一个名字 选一个.net框架&#xff0c;我这里选…

电脑开机出现:CLIENT MAD ADDR (网卡启动系统)的解决办法

文章目录 前言步骤1、确定情况2、对症下药——关闭网卡启动 补充1、关于BIOS2、关于PXE 前言 最近给旧电脑重装系统安了下开发环境和常用软件啥的&#xff0c;之前还好好启动的电脑&#xff0c;开机突然需要额外加载一个页面&#xff0c;虽然最后正常启动了不影响使用&#xf…

60.Sentinel源码分析

Sentinel源码分析 1.Sentinel的基本概念 Sentinel实现限流、隔离、降级、熔断等功能&#xff0c;本质要做的就是两件事情&#xff1a; 统计数据&#xff1a;统计某个资源的访问数据&#xff08;QPS、RT等信息&#xff09; 规则判断&#xff1a;判断限流规则、隔离规则、降级规…