一、抽象类


// 抽象类
public abstract class Logger {private String name;private boolean enabled;private Level minPermittedLevel;public Logger(String name, boolean enabled, Level minPermittedLevel) {this.name = name;this.enabled = enabled;this.minPermittedLevel = minPermittedLevel;}public void log(Level level, String message) {boolean loggable = enabled && (minPermittedLevel.intValue() <= level.intValue());if (!loggable) return;doLog(level, message);}protected abstract void doLog(Level level, String message);
}
// 抽象类的子类:输出日志到文件
public class FileLogger extends Logger {private Writer fileWriter;public FileLogger(String name, boolean enabled,Level minPermittedLevel, String filepath) {super(name, enabled, minPermittedLevel);this.fileWriter = new FileWriter(filepath); }@Overridepublic void doLog(Level level, String mesage) {// 格式化level和message,输出到日志文件fileWriter.write(...);}
}
// 抽象类的子类: 输出日志到消息中间件(比如kafka)
public class MessageQueueLogger extends Logger {private MessageQueueClient msgQueueClient;public MessageQueueLogger(String name, boolean enabled,Level minPermittedLevel, MessageQueueClient msgQueueClient) {super(name, enabled, minPermittedLevel);this.msgQueueClient = msgQueueClient;}@Overrideprotected void doLog(Level level, String mesage) {// 格式化level和message,输出到消息中间件msgQueueClient.send(...);}
}
  1. 抽象类不能被实例化,只能被继承。不能同过new方法去实例化一个抽象类
  2. 抽象类可以包括属性和方法。方法可以包括实现,即普通方法; 方法也可以不包括实现,即抽象方法。
  3. 子类继承抽象类,必须实现抽象类中的抽象方法。若没有实现,运行将会报错

二、接口类


// 接口
public interface Filter {void doFilter(RpcRequest req) throws RpcException;
}
// 接口实现类:鉴权过滤器
public class AuthencationFilter implements Filter {@Overridepublic void doFilter(RpcRequest req) throws RpcException {//...鉴权逻辑..}
}
// 接口实现类:限流过滤器
public class RateLimitFilter implements Filter {@Overridepublic void doFilter(RpcRequest req) throws RpcException {//...限流逻辑...}
}
// 过滤器使用demo
public class Application {// filters.add(new AuthencationFilter());// filters.add(new RateLimitFilter());private List<Filter> filters = new ArrayList<>();public void handleRpcRequest(RpcRequest req) {try {for (Filter filter : fitlers) {filter.doFilter(req);}} catch(RpcException e) {// ...处理过滤结果...}// ...省略其他处理逻辑...}
}
  1. 接口不能包含属性(即不能包含成员变量)
  2. 接口类中只能声明方法,不能包含方法的实现(这点类似抽类中的抽象方法)
  3. 类实现抽象接口时,必须实现其中所有的抽象方法

抽象类与接口类的对比来讲,抽象类可以包含属性,主要是为解决代码复用的问题,和子类继承是is-a的关系。

接口类是为了解决解耦问题,调用者更多只需关注抽象接口,不需要关注实现。也是“基于接口而非实现进行编程”的体现。表示的一种has-a的关系。

在解决代码复用的问题上,如果单纯的用继承,势必要在父类中增加一些没有实现的方法,在代码阅读是增加负担,同时调用者在未能全部熟悉代码的前提下,忘记填写实现方法,在调用的时候会出错。同时可以实例化该父类也是危险的。

关于抽象类和接口类的使用:

抽象类是一种自下而上设计思路,先有代码重复,抽象出一个类,解决代码复用问题。这里重点要区别现有单纯的继承,单纯的继承父类会被实例化,防止从而调用了没有实现的方法(同时没有报错)。

接口类是一种自上而下设计思路,先设计好接口,再去实现。

3.2更新:

C++模拟接口:

class Strategy{public:~Strategy();virtual void algorithm();protected:Strategy()
}

将函数声明成虚,子类继承后,需要实现,同时C++只包含虚函数的虚基类,不能实例化,不包含任何属性。来模拟Java中interface。

JAVA普通类模拟接口:

class Strategy{protected Strategy(){}public void funA(){throw new MethodUnSupportedException();}
}

将构造函数声明成protected避免外界直接实例化,同时函数直接抛出异常,只有按照继承重写,实现接口:不含属性、不能直接实例化、函数接口直接调用抛出异常。

关于基于接口而非实现进行编程:

越抽象、越顶层、脱离具体实现的接口,在日后面对需求变化时,上游系统可以保持最少或没有变化。文中的关于图片上传到云端的例子,总结一下。首先基于阿里云上传设计了一个如下的类:


public class AliyunImageStore {//...省略属性、构造函数等...public void createBucketIfNotExisting(String bucketName) {// ...创建bucket代码逻辑...// ...失败会抛出异常..}public String generateAccessToken() {// ...根据accesskey/secrectkey等生成access token}public String uploadToAliyun(Image image, String bucketName, String accessToken) {//...上传图片到阿里云...//...返回图片存储在阿里云上的地址(url)...}public Image downloadFromAliyun(String url, String accessToken) {//...从阿里云下载图片...}
}// AliyunImageStore类的使用举例
public class ImageProcessingJob {private static final String BUCKET_NAME = "ai_images_bucket";//...省略其他无关代码...public void process() {Image image = ...; //处理图片,并封装为Image对象AliyunImageStore imageStore = new AliyunImageStore(/*省略参数*/);imageStore.createBucketIfNotExisting(BUCKET_NAME);String accessToken = imageStore.generateAccessToken();imagestore.uploadToAliyun(image, BUCKET_NAME, accessToken);}}

这里包括几个步骤:1创建bucket 2生成Token 3 上传 4下载。在图片上传变成自家私有云后,需要修改接口,这时候的Token就不需要了,同时名字上也有歧义,uptoaliyun在其他地方势必造成歧义,于是重新设计一个接口类,只保留上传和下载两个功能。


public interface ImageStore {String upload(Image image, String bucketName);Image download(String url);
}public class AliyunImageStore implements ImageStore {//...省略属性、构造函数等...public String upload(Image image, String bucketName) {createBucketIfNotExisting(bucketName);String accessToken = generateAccessToken();//...上传图片到阿里云...//...返回图片在阿里云上的地址(url)...}public Image download(String url) {String accessToken = generateAccessToken();//...从阿里云下载图片...}private void createBucketIfNotExisting(String bucketName) {// ...创建bucket...// ...失败会抛出异常..}private String generateAccessToken() {// ...根据accesskey/secrectkey等生成access token}
}// 上传下载流程改变:私有云不需要支持access token
public class PrivateImageStore implements ImageStore  {public String upload(Image image, String bucketName) {createBucketIfNotExisting(bucketName);//...上传图片到私有云...//...返回图片的url...}public Image download(String url) {//...从私有云下载图片...}private void createBucketIfNotExisting(String bucketName) {// ...创建bucket...// ...失败会抛出异常..}
}// ImageStore的使用举例
public class ImageProcessingJob {private static final String BUCKET_NAME = "ai_images_bucket";//...省略其他无关代码...public void process() {Image image = ...;//处理图片,并封装为Image对象ImageStore imageStore = new PrivateImageStore(...);imagestore.upload(image, BUCKET_NAME);}
}

这时的ImageProcessingJob在使用时候,只需要依赖upload,download两个函数就好。也就是在基于接口,而非实现进行编程。这里总结出2个规则:

一、软件的编写要有足够的抽象意识,接口意识,在日后面对需求变化,可以更好的提高代码通用性。

二、接口命名要脱离具体实现,例如例子中上传到阿里云,就不够通用。

最后还有个问题:

Image image = ...;//处理图片,并封装为Image对象
ImageStore imageStore = new PrivateImageStore(...);
imagestore.upload(image, BUCKET_NAME);

图片处理过程,不可避免的写入 new PrivateImageStroe(),避免这种写法,工厂模式+Config文件,

ImageStore imageStore = ImageStoreFactory.newInstance(SOTRE_TYPE_CONFIG);
config文件可以写类似properties的文件

最近在工作中,遇到工厂模式是在创建不同地图实例图标上。

【设计模式】抽象类与接口相关推荐

  1. JavaSE自学笔记013_Real(抽象类、接口、两种设计模式)

    JavaSE自学笔记013_Real(抽象类.接口) 一.基本概述 (一)抽象类(关键字:abstract) //抽象方法 public abstract class Animal{abstract ...

  2. day03--java基础编程:面向对象,构造方法,代码块讲解,this super,static,final,访问修饰符,方法重写,向上/下造型,main方法,抽象类,接口,设计模式,异常,内部类

    1 Day06–面向对象1 1.1 面向对象 1.1.1 概念 推荐看的书:Thinking in java 概念:所谓的面向对象是一种编程思想,通过这种思想可以把生活中的复杂事情变得简单化,从原来的 ...

  3. Python设计模式二:接口类和抽象类(Python接口设计)

    系列文章目录 Python设计模式一:面向对象编程 文章目录 系列文章目录 前言 一.接口类和抽象类是什么? 基于接口编程而非实现 二.Python里如何实现接口类和抽象类? 三.接口类和抽象类的应用 ...

  4. day03--java基础编程:面向对象,构造方法,代码块讲解,this super,static,final,访问修饰符,方法重写,向上_下造型,main方法,抽象类,接口,设计模式,异常,内部类

    1 Day06–面向对象1 1.1 面向对象 1.1.1 概念 推荐看的书:Thinking in java 概念:所谓的面向对象是一种编程思想,通过这种思想可以把生活中的复杂事情变得简单化,从原来的 ...

  5. 抽象类与接口与模板方法设计模式

    抽象类特点: 1,抽象方法一定在抽象中. 2,抽象方法和抽象类都必须被abstract关键字修饰. 3,抽象不可以用new创建对象,因为调用抽象方法没意义. 4,抽象类中的抽象方法要被使用,必须由子类 ...

  6. java 单例内部类_9 java的关键字static、单例设计模式、初始化块、关键字final、抽象类、接口、内部类...

    static关键字 当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用.我们有时 ...

  7. Java查漏补缺(08)关键字:static、单例设计模式、理解main方法、类的成员之四:代码块、final关键字、抽象类、接口、内部类、枚举类、注解、包装类

    Java查漏补缺(08)关键字:static.单例设计模式.理解main方法.类的成员之四:代码块.final关键字.抽象类.接口.内部类.枚举类.注解.包装类 本章专题与脉络 1. 关键字:stat ...

  8. 【设计模式之美】<Reading Notes>抽象类与接口

    抽象类特性 1.抽象类不允许被实例化,只能被继承. 2.抽象类可以包含属性和方法.方法既可以包含代码实现,也可以不包含代码实现.不包含代码实现的方法叫做抽象方法. 3.子类继承抽象类,必须实现抽象类中 ...

  9. 抽象类与接口的一个程序实现

    /** 本程序实现抽象类与接口的基本操作* 对比接口与抽象类操作的区别* 其中的一个设计模式:工厂设计模式:A-C 直接.这样会造成耦合性过强.工厂设计模式加一个桥梁由A-B-C * 实现间接访问*/ ...

最新文章

  1. R语言诊断试验数据处理与ROC分析实战案例2
  2. java学习笔记--java中的基本数组[5]
  3. 3GU仙果游戏达成三地技术引擎战略合作联盟
  4. 智能算法的研究与实现
  5. 前端解析返回的对象时json显示$ref问题的解决
  6. 3个多月,近3000人参与的源码共读,诚邀加入~
  7. 初探mysql数据库模式(一)
  8. Win7/8出现An error occurred on the server when processing the URL解决办法
  9. 关于 Service 设计初步(MSDN节选翻译)
  10. 自动生成三层结构代码(2)--生成实体类
  11. BZOJ44084299[Fjoi 2016]神秘数——主席树
  12. 高中数学函数思维导图的绘制方法分享
  13. 语音处理基础:预加重、分帧、帧移、加窗、傅里叶变换
  14. 相见恨晚 linux下的c++filt 命令
  15. pnuts系统的局限性_水平系统的局限性
  16. 【华为云计算产品系列】云上迁移工具RainBow实战详解
  17. altium designer 绘制pcb时如何检查漏线
  18. jdk groovy版本_Groovy JDK(GDK):日期和日历
  19. sighold,sigset,sigrelse,sigpause,sigignore
  20. 解决安装程序无法初始化。请下载Adobe

热门文章

  1. Mac下如何用SSH连接远程Linux服务器
  2. iOS 学习之旅 - OC 篇
  3. 关于软件工程----一线城市与二三线城市的区别
  4. Google地图之野望:你所不知道的背后故事
  5. 2019年,4亿行代码背后的故事
  6. java回顾:MyBatis参数、sql片段、动态sql、高级查询
  7. .NET高级工程师面试经历
  8. Alpha冲刺——第八天
  9. NB-IoT和LTE远程通讯方案选择
  10. NB-iot网络架构组成简介