前言
面向抽象原则是面向对象四大基本原则的第一条,其重要性不言而喻,面向抽象原则分为抽象类、接口以及面向抽象编程,在之前的内容中我们详细介绍了抽象类与接口,并对二者进行了对比,在本文中我们将详细介绍什么是面向抽象编程,它与传统编程相比有什么优势?在开发中又该如何切实应用。
一、什么是面向抽象编程?
面向抽象编程就是在设计一个类时,不让该类面向具体的类,而是面向抽象类或接口,即所设计的类中的重要数据是抽象类或接口声明的变量,而不是具体类声明的变量。
下面我们将在具体的案例中进一步分析传统类设计与面向抽象编程的类设计的区别。
二、传统场景的类设计
在探讨面向抽象编程之前,先看一下我们常规对于一个类的设计是什么样的。
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;// 定义一个常量
### 架构学习资料
![准备两个月,面试五分钟,Java中高级岗面试为何越来越难?](https://img-blog.csdnimg.cn/img_convert/04567ef25ff4bc6be1f8c0b11eff66e8.webp?x-oss-process=image/format,png)
![准备两个月,面试五分钟,Java中高级岗面试为何越来越难?](https://img-blog.csdnimg.cn/img_convert/2eaf8ead5bd74c7f9fccb100ed86a606.webp?x-oss-process=image/format,png)
![准备两个月,面试五分钟,Java中高级岗面试为何越来越难?](https://img-blog.csdnimg.cn/img_convert/36db70874d0d064c394fc9346aed8aa9.webp?x-oss-process=image/format,png)
![准备两个月,面试五分钟,Java中高级岗面试为何越来越难?](https://img-blog.csdnimg.cn/img_convert/82ef06f77778e160674dd4a548bff2cf.webp?x-oss-process=image/format,png)
![准备两个月,面试五分钟,Java中高级岗面试为何越来越难?](https://img-blog.csdnimg.cn/img_convert/50a233eb46e62055df0f3498adf18c88.webp?x-oss-process=image/format,png)
> 由于篇幅限制小编,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
]
[外链图片转存中...(img-N8ugIsIs-1714318446041)]
[外链图片转存中...(img-Mhqmox1I-1714318446043)]
[外链图片转存中...(img-TEAhp967-1714318446044)]
> 由于篇幅限制小编,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
> **本文已被[CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】](https://bbs.csdn.net/topics/618154847)收录**