文章目录

  • 前言
  • 一、什么是面向抽象编程?
  • 二、传统场景的类设计
    • 2.1、项目场景设计
    • 2.2、传统类设计存在的问题
  • 三、采用面向抽象编程的类设计
    • 3.1、设计一个抽象类/接口
    • 3.2、采用上转型对象/接口回调调用子类方法
    • 3.3、重新设计子类/被实现类
    • 3.4、面向抽象编程的具体实现
  • 四、面向抽象编程的优势
  • 总结

前言

面向抽象原则是面向对象四大基本原则的第一条,其重要性不言而喻,面向抽象原则分为抽象类、接口以及面向抽象编程,在之前的内容中我们详细介绍了抽象类与接口,并对二者进行了对比,在本文中我们将详细介绍什么是面向抽象编程,它与传统编程相比有什么优势?在开发中又该如何切实应用。


一、什么是面向抽象编程?

面向抽象编程就是在设计一个类时,不让该类面向具体的类,而是面向抽象类或接口,即所设计的类中的重要数据是抽象类或接口声明的变量,而不是具体类声明的变量

下面我们将在具体的案例中进一步分析传统类设计与面向抽象编程的类设计的区别。

二、传统场景的类设计

在探讨面向抽象编程之前,先看一下我们常规对于一个类的设计是什么样的。

2.1、项目场景设计

项目场景:现在我们需要求一个圆柱体的体积,需要创建两个类,圆类 Circle 和圆柱体类 Pillar。

首先我们创建一个 Circle 类,该类创建的对象 circle 调用 getArea() 方法可以计算出圆的面积,Circle 类的代码如下:

package com.bailu.principle;public class Circle {final double PI = 3.14159;// 定义一个常量double r;/** 定义一个无参构造*/Circle() {}Circle(double r) {this.r = r;}public double getArea() {return (PI * r * r);}
}

接着我们再设计一个圆柱类 Pillar,该类创建的对象 pillar 调用 getVolume() 方法可以计算圆柱体的体积,Pillar 类的代码如下:

package com.bailu.principle;public class Pillar {Circle bottom;// 将Circle类声明的对象作为成员,圆柱体的底double height;/** 定义一个无参构造*/Pillar() {}Pillar(Circle bottom, double height) {this.bottom = bottom;this.height = height;}public double getVolume() {return bottom.getArea() * height;}
}

2.2、传统类设计存在的问题

在上面的圆柱体类 Pillar 中,bottom 是用具体类 Circle 声明的变量,如果在实际开发中不涉及用户需要的变化,这样设计并没有什么不妥,但是某些时候,如果用户希望将圆柱体改为三菱柱。显然 Pillar 类是无法满足的,并不能满足用户的需求

那我们就需要对 Pillar 类进行修改。对于需要我们需要明确,柱体计算体积关键点在于计算底面积。我们不应该关心它的底具体是什么样的形状,而应该关心是否有计算面积的方法。

即我们在设计类的时候不应该将柱体的底看做某个具体类声明的变量,我们上面这样做,Pillar 类太过于依赖具体类,缺乏弹性,难以应对需求的变化

三、采用面向抽象编程的类设计

3.1、设计一个抽象类/接口

如果我们采用面向抽象编程重新进行设计,首先需要设计一个抽象类用来获取柱体底面积,该抽象类(或接口)我们定义为 Geometry(),我们在其中定义一个 getArea() 的抽象方法,具体代码如下:

package com.bailu.principle;public abstract class Geometry {// 如果使用的是接口,用interface定义即可public abstract double getArea();
}

现在我们就可以面向 Geometry 类进行编码,即通过上转型对象/接口回调的方式,调用 Geometry 子类重写的 getArea() 方法,这样 Pillar 类就可以将计算柱体底面积的任务指派给 Geometry 子类的实例

3.2、采用上转型对象/接口回调调用子类方法

现在我们重新设计 Pillar 类不再依赖具体类,而是面向我们创建的抽象类/接口 Geometry,即 bottom 不再是具体类 Circle 声明的变量,重新设计后 Pillar 类代码如下:

package com.bailu.principle;public class Pillar {Geometry bottom;// bottom是抽象类Geometry声明的变量double height;/** 定义一个无参构造*/Pillar() {}Pillar(Geometry bottom, double height) {this.bottom = bottom;this.height = height;}public double getVolume() {return bottom.getArea() * height;// bottom可以调用子类重写的getArea()方法}
}

3.3、重新设计子类/被实现类

在采用面向抽象编程之后,我们就可以根据客户需求对柱体要求的不同底进行设计。如圆形底和矩形底,我们创建抽象类 Geometry 的子类 Circle 和 Rectangle,重写 Geometry 类的抽象方法 getArea()计算各自面积。

Circle 类对应代码如下:

package com.bailu.principle;/** 当柱体的底为圆时*/
public class Circle extends Geometry {final double PI = 3.14159;// 定义一个常量double r;/** 定义一个无参构造*/Circle() {}Circle(double r) {this.r = r;}@Overridepublic double getArea() {return (PI * r * r);}
}

Rectangle 类对应代码如下:

package com.bailu.principle;/** 当柱体的底为矩形时*/
public class Rectangle extends Geometry {double a, b;// 定义矩形的长宽/** 创建一个无参构造*/Rectangle() {}Rectangle(double a, double b) {this.a = a;this.b = b;}@Overridepublic double getArea() {return a * b;}
}

3.4、面向抽象编程的具体实现

现在我们就可以使用 Pillar 类创建出不同形状底的柱体了,实现代码如下:

package com.bailu.principle;public class ApplicationPillar {public static void main(String[] args) {Pillar pillar;Geometry bottom;bottom = new Rectangle(2, 3);// 抽象类的实例作为Rectangle类的上转型对象pillar = new Pillar(bottom, 3);System.out.println("矩形底柱体体积为: " + pillar.getVolume());bottom = new Circle(2);// 抽象类的实例作为Circle类的上转型对象pillar = new Pillar(bottom,2);System.out.println("圆底柱体体积为: " + pillar.getVolume());}
}

运行结果具体如下图所示:

四、面向抽象编程的优势

通过上面的案例我们可以发现,采用面向编程来设计 Pillar 类,使得 Pillar 类不再依赖于具体的某个类(Circle 类、Rectangle 类),当我们有新的需求增加时,我们只需要增加 Geometry 的子类即可,如增加一个三角形底的子类 Triangle,并不需要修改 Pillar 类的任何代码就可以创建出三角形底的柱体


总结

在本文给大家介绍了什么是面向抽象编程,并通过与传统类设计的对比使大家明确面向抽象编程的优势,设计一个类时,不让该类面向具体的类,而是面向抽象类或接口,即所设计的类中的重要数据是抽象类或接口声明的变量,而不是具体类声明的变量,这样就算需求发生变化,我们只需要增加或修改抽象类子类内容即可,而无需修改其他代码。


我是白鹿,一个不懈奋斗的程序猿。望本文能对你有所裨益,欢迎大家的一键三连!若有其他问题、建议或者补充可以留言在文章下方,感谢大家的支持!

Java 设计模式 Day3 之面向抽象原则:什么是面向抽象编程?面向抽象编程如何应用?相关推荐

  1. 引用防删——JAVA设计模式总结之六大设计原则

    JAVA设计模式总结之六大设计原则 从今年的七月份开始学习设计模式到9月底,设计模式全部学完了,在学习期间,总共过了两篇:第一篇看完设计模式后,感觉只是脑子里面有印象但无法言语.于是决定在看一篇,到9 ...

  2. java设计模式3,里氏替换原则

    目录 一.里氏替换原则定义 二.里氏替换原则的作用 三.违背原则场景 四.里氏替换原则改变代码 1.抽象人物类 2.哪吒子类 3.敖丙子类 五.关注公众号哪吒编程,回复1024,获取Java学习资料, ...

  3. 依赖倒置原则——举例说明Java设计模式中的依赖倒置原则

    依赖倒置原则--举例说明Java设计模式中的依赖倒置原则 一.前言 看官方定义 二.举例说明 2.1 例子介绍(无聊的可看看,着急的请跳过) 2.2 反例 2.1.1 反例1 (1)类图说明 (2)代 ...

  4. 里氏替换原则——举例说明Java设计模式中的里氏替换原则

    里氏替换原则--举例说明Java设计模式中的里氏替换原则 1. 前言 官方定义: 2. 举例说明 2.1 例子介绍 2.2 反例 2.2.1 类图说明 2.2.2 代码说明 2.2.3 测试 2.2. ...

  5. Java设计模式:农场不同季节生成不同蔬菜水果的一种抽象工厂模式

    Java设计模式:农场不同季节生成不同蔬菜水果的一种抽象工厂模式 /*** 农场的抽象.不同季节生产不同的蔬菜和水果.*/ public interface Farm {//不同季节,不同蔬菜和水果. ...

  6. 接口隔离原则——举例说明Java设计模式中的接口隔离原则

    举例说明Java设计模式中的接口隔离原则 一.举例说明 1.反例 (1)类图说明 (2)代码说明 (3)测试 (4)分析缺点(总结) 2.正例 (1)类图说明 (2)代码说明 (3)测试 (4)方案评 ...

  7. Java 设计模式总结及六大设计原则

    设计模式总结 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式. ...

  8. java设计模式总结之六大设计原则(有图有例子)

    转载:https://www.cnblogs.com/jpfss/p/9765239.html 下面来总结下自己所学习的设计模式,首先我们看下各个模式之间的关系图,下面这张图是网上比较典型的一个类图关 ...

  9. Java设计模式总结——6大设计原则

    从今年的七月份开始学习设计模式到9月底,设计模式全部学完了,在学习期间,总共过了两篇:第一篇看完设计模式后,感觉只是脑子里面有印象但无法言语.于是决定在看一篇,到9月份第二篇设计模式总于看完了,这一篇 ...

最新文章

  1. ASP调用存储过程返回了一个参数和一个记录集时出现ADODB.Recordset 错误 '800a0e78'...
  2. 在fedora21 上的php+mysql+apache环境搭建
  3. Vue如何获取当前时间
  4. 观星(计算几何/凸包/多边形面积)
  5. 慕课网_《Java实现对称加密》学习总结
  6. 微信小程序 - 实践- 001-实现一个多TAB的菜单框架
  7. c# 跨线程访问窗体UI
  8. Linux操作系统各版本ISO镜像下载(包括oracle linux\redhat\centos\u
  9. JavaScript比较是否在某时间段内
  10. 论耐力,哺乳动物中人类可能是第一
  11. STC单片机程序下载实战
  12. QNAP 威联通 NAS的个人使用经验 篇三:#剁主计划-西安# 时隔3年,NAS使用须知
  13. 开发Linux应用程序的三种方法
  14. 如何调节pycharm字体大小
  15. 《阿里巴巴Java开发手册(正式版)》--安全规约
  16. Bootstrap3 和 Bootstrap4 的区别
  17. 【博客438】Kubernetes IPAM分配IP原理
  18. 如何解决error: failed to push some refs to ‘https://gitee.com/
  19. Linux——man命令
  20. 使用 MyBatis 的 Maven 插件生成代码

热门文章

  1. java 寻找和为定值的多个数_算法笔记_037:寻找和为定值的两个数(Java)
  2. 自定义导航页_带你回归“真”的导航页
  3. 频谱扩展 matlab,语音信号频谱扩展
  4. docker-compose 实战案例
  5. IntelliJ IDEA 2020 基础设置
  6. -bash: lsof: 未找到命令
  7. 实战04_redis-cluster集群搭建
  8. 系统机构设计师 - 软件质量属性
  9. 前端的葵花宝典 - 红宝书《JavaScript高级程序设计(第4版)》学习笔记
  10. 前端学习笔记之 创建节点 与 添加节点案例