Java 抽象类VS接口VS普通类

本文探讨了如何恰当地使用接口,通过区分稳定功能和不稳定需求,实现接口与实现的解耦。通过实例说明抽象类与接口的选择原则,并揭示了如何在抽象类中利用多态性。重点在于理解何时使用接口和抽象类来提升代码灵活性和可维护性。
摘要由CSDN通过智能技术生成

关于接口 再来理解一下

接口 interface,提供了代码抽象的能力,但没有必要给每个类都创建一个接口 interface,这里要掌握一个度,抽象:只关注 功能点,不关心具体实现
那么这个”度“就是:
接口和实现分离,封装不稳定的实现,暴露稳定的接口

那什么是是稳定的?
什么是不稳定的?

1.比如我的系统有一个功能为上传图片,那么存储图片这个功能点是稳定的(不会经常变的)就是上传图片,但是需求是经常变的,今天PM想存储至QiNiu,明天想存储至AiLi,这时我们就可以定义一个interface 为ImageStore,暴露稳定的功能点 saveImage()给调用方,随便具体实现怎么变,调用方的代码不用变
2.比如后端给前端 提供一组 HTTP API,不管API内部的代码怎么改变,API URL上面的PATH是不容易变的

抽象类 对比 接口

抽象类:is-a的关系, 如果确定是is-a的关系 ,就可以用抽象类.
接口: has-a的关系,如果确定是has-a的关系 ,就可以用interface

两者都具有多态的特性:父类能引用子类,父类能动态调用子类的方法,子类需要实现自己的方法

interface的function和 protected abstract void 的function,都是需要子类重写的,然后父类引用子类,然后父类动态的调用方法,暴露给外部的是小范围的(公共的部分 父类有的)

public class AbstarctClassVSInterface {
   public static void main(String[] args) {
       Logger fileLogger = new FileLogger("文件记录器", true, "1", "/bin/bash");
       // 动态调用子类方法
       fileLogger.log("hello");
       // 动态调用子类方法
       Logger mqLogger = new MQLogger("消息队列记录器", true, "1", "kafka");
       mqLogger.log("world");

   }
}

abstract class Logger {
   private String name;
   private boolean enabled;
   private String logLevel;

   public Logger(String name, boolean enabled, String logLevel) {
       this.name = name;
       this.enabled = enabled;
       this.logLevel = logLevel;
   }

   public void log(String message) {
       if (!this.enabled) {
           return;
       }
       doLog(this.logLevel, message);
   }

   protected abstract void doLog(String logLevel, String message);
}

class FileLogger extends Logger {
   private String filepath;

   public FileLogger(String name, boolean enabled, String logLevel, String filepath) {
       super(name, enabled, logLevel);
       this.filepath = filepath;
   }

   @Override
   protected void doLog(String logLevel, String message) {
       System.out.println("I AM File logger" + logLevel + message);
   }
}

class MQLogger extends Logger {
   private String MQName;

   public MQLogger(String name, boolean enabled, String logLevel, String MQName) {
       super(name, enabled, logLevel);
       this.MQName = MQName;
   }

   @Override
   protected void doLog(String logLevel, String message) {
       System.out.println("I AM MQ logger" + logLevel + message);
   }
}

抽象类 对比 普通类

1.如果这里不添加doLog 方法,就不能利用多态性,
2.添加了一个空方法 又会引起歧义,
3.而且这个不是子类强制重写的,有可能子类忘重写了

/**
 *   抽象类对比普通类
 *   如果 Logger是普通类
 */
public class NormalClassVSAbstractClass {
}
 class NormalLogger {
    private String name;
    private boolean enabled;
    private String logLevel;

    public NormalLogger(String name, boolean enabled, String logLevel) {
        this.name = name;
        this.enabled = enabled;
        this.logLevel = logLevel;
    }

    public void log(String message) {
        if (!this.enabled) {
            return;
        }
        doLog(this.logLevel, message);
    }
  
    protected  void doLog(String logLevel, String message){

    }
}

class NormalFileLogger extends NormalLogger {
    private String filepath;

    public NormalFileLogger(String name, boolean enabled, String logLevel, String filepath) {
        super(name, enabled, logLevel);
        this.filepath = filepath;
    }

//    @Override
//    protected void doLog(String logLevel, String message) {
//        System.out.println("I AM File logger" + logLevel + message);
//    }
}

class NormalMQLogger extends NormalLogger {
    private String MQName;

    public NormalMQLogger(String name, boolean enabled, String logLevel, String MQName) {
        super(name, enabled, logLevel);
        this.MQName = MQName;
    }

//    @Override
//    protected void doLog(String logLevel, String message) {
//        System.out.println("I AM MQ logger" + logLevel + message);
//    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值