关于接口 再来理解一下
接口 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);
// }
}