面向过程与面向对象的概念
面向过程:当需要实现一个功能的时候,每一个具体的步骤都要亲力亲为,详细处理每一个细节。强调步骤。
面向对象:当需要实现一个功能的时候,不关心具体的步骤,而是找一个已经具有该功能的人,来帮我做事儿。强调对象。
面向过程与面向对象的比较
面向过程 | 面向对象 |
---|---|
性能相对来说更高 | 性能相对来说比面向过程低 |
但不易维护、不易复用、不易扩展 |
易维护、易扩展、易复用 |
因为类调⽤时需要实例化,开销⽐较⼤,⽐较消耗资源,所以当性能是最重要的考量因素的时候,⽐如单⽚机、嵌⼊式开发、Linux/Unix 等⼀般采⽤⾯向过程开发。
因为⾯向对象有封装、继承、多态性的特性,所以可以设计出低耦合的系统,使系统更加灵活、更加易于维护。
代码实现
下面以网络上关于面向对象与面向过程经典的解释——把大象装进冰箱来举例说明:
public class Demo {
public static void main(String[] args) {
/*
把大象装进冰箱的步骤:
1.打开冰箱门
2.把大象装进冰箱
3.关闭冰箱门
*/
// 使用面向过程的方式
po();
// 使用面向对象的方式
oo();
}
// 使用面向过程的方式,即一步一步按照步骤来
public static void po(){
// 第一步:打开冰箱门
System.out.println("打开冰箱门");
// 第二步:把大象装进冰箱
System.out.println("把大象装进冰箱");
// 第三步:关闭冰箱门
System.out.println("关闭冰箱门");
// 到现在为止,完成所有步骤,已经将大象关进冰箱了
}
// 使用面向对象的方式,即创建一个冰箱对象,让冰箱来打开、装大象、关门,我们只需要调用它的方法就可以了
public static void oo(){
// 实例化一个冰箱对象,让冰箱来完成这些操作
Refrigerator refrigerator=new Refrigerator();
// 调用方法,打开冰箱门
refrigerator.open();
// 调用方法,把大象装进冰箱
refrigerator.putElephant();
// 调用方法,关闭冰箱门
refrigerator.close();
}
}
/**
* 这是一个冰箱类,该类有操作冰箱的方法,如打开冰箱门等
*/
class Refrigerator{
public void open(){
System.out.println("打开冰箱门");
}
public void putElephant(){
System.out.println("把大象装进冰箱");
}
public void close(){
System.out.println("关闭冰箱门");
}
}
在上面的代码中,面向过程是每一个步骤都要亲自实现,而面向对象是在冰箱类中有相关的方法,直接调用就可以了。
这个代码主要体现的是面向对象与面向过程可复用性、扩展性、维护性,而没有体现到性能的比较。
上述代码已经实现了把大象装进冰箱的功能,现在来了个新需求,要求大象转圈,转圈后才装进冰箱,现在代码如下:
public class Demo {
public static void main(String[] args) {
/*
把大象装进冰箱的步骤:
1.打开冰箱门
2.把大象装进冰箱
3.关闭冰箱门
*/
// 使用面向过程的方式
po(5);
// 使用面向对象的方式
oo();
}
// 使用面向过程的方式,即一步一步按照步骤来
public static void po(int num){
// 新需求:转圈,不知道要求转几圈,所以传个参数进来
for (int i = 0; i < num; i++) {
System.out.println("大象已经转第 "+(i+1)+" 圈了");
}
// 第一步:打开冰箱门
System.out.println("打开冰箱门");
// 第二步:把大象装进冰箱
System.out.println("把大象装进冰箱");
// 第三步:关闭冰箱门
System.out.println("关闭冰箱门");
// 到现在为止,完成所有步骤,已经将大象关进冰箱了
}
// 使用面向对象的方式,即创建一个冰箱对象,让冰箱来打开、装大象、关门,我们只需要调用它的方法就可以了
public static void oo(){
// 实例化一个冰箱对象,让冰箱来完成这些操作
Refrigerator refrigerator=new Refrigerator();
// 新需求:转圈
refrigerator.round(5);
// 调用方法,打开冰箱门
refrigerator.open();
// 调用方法,把大象装进冰箱
refrigerator.putElephant();
// 调用方法,关闭冰箱门
refrigerator.close();
}
}
/**
* 这是一个冰箱类,该类有操作冰箱的方法,如打开冰箱门等
*/
class Refrigerator{
public void round(int num){
for (int i = 0; i < num; i++) {
System.out.println("大象已经转第 "+(i+1)+" 圈了");
}
}
public void open(){
System.out.println("打开冰箱门");
}
public void putElephant(){
System.out.println("把大象装进冰箱");
}
public void close(){
System.out.println("关闭冰箱门");
}
}
现在又有一个新的需求,要求大象跳个舞,代码实现如下:
public class Demo {
public static void main(String[] args) {
/*
把大象装进冰箱的步骤:
1.打开冰箱门
2.把大象装进冰箱
3.关闭冰箱门
*/
// 使用面向过程的方式
po(5,"芭蕾舞");
// 使用面向对象的方式
oo();
}
// 使用面向过程的方式,即一步一步按照步骤来
public static void po(int num,String dance){
// 新需求:转圈,不知道要求转几圈,所以传个参数进来
for (int i = 0; i < num; i++) {
System.out.println("大象已经转第 "+(i+1)+" 圈了");
}
// 新需求:跳舞,不知道要跳什么舞蹈,所以传个参数进来
System.out.println("大象跳个"+dance);
// 第一步:打开冰箱门
System.out.println("打开冰箱门");
// 第二步:把大象装进冰箱
System.out.println("把大象装进冰箱");
// 第三步:关闭冰箱门
System.out.println("关闭冰箱门");
// 到现在为止,完成所有步骤,已经将大象关进冰箱了
}
// 使用面向对象的方式,即创建一个冰箱对象,让冰箱来打开、装大象、关门,我们只需要调用它的方法就可以了
public static void oo(){
// 实例化一个冰箱对象,让冰箱来完成这些操作
Refrigerator refrigerator=new Refrigerator();
// 新需求:转圈
refrigerator.round(5);
// 新需求:跳舞
refrigerator.dance("芭蕾舞");
// 调用方法,打开冰箱门
refrigerator.open();
// 调用方法,把大象装进冰箱
refrigerator.putElephant();
// 调用方法,关闭冰箱门
refrigerator.close();
}
}
/**
* 这是一个冰箱类,该类有操作冰箱的方法,如打开冰箱门等
*/
class Refrigerator{
public void round(int num){
for (int i = 0; i < num; i++) {
System.out.println("大象已经转第 "+(i+1)+" 圈了");
}
}
public void dance(String dance){
System.out.println("大象跳个"+dance);
}
public void open(){
System.out.println("打开冰箱门");
}
public void putElephant(){
System.out.println("把大象装进冰箱");
}
public void close(){
System.out.println("关闭冰箱门");
}
}
可以发现面向过程的代码随着功能需求的增加,代码的可维护性越来越差了,可扩展性也不是很好了,而面向对象只需要在类中添加一个方法,实现对应功能即可,但面向过程的所有功能逻辑代码都写在一个方法体内。
现在的新需求是,不要大象转圈了,所以那么要删除相关代码,或者注释掉:
面向过程需要注释的地方:
面向对象需要注释的地方:
看,如果面向过程中一个方法内有大量的执行步骤,如果需要增加或删除,这是很麻烦的,而且很难维护。
(注意:大象跳舞、转圈的方法写错类了,该单独写在大象类中,而不是写在笼子类中,在面向对象思路中。)
现在又来了个新需求,要把大象装进冰箱后,放出后,又要装进笼子,现在就是扩展功能了,那么如何实现呢?
public class Demo {
public static void main(String[] args) {
/*
把大象装进冰箱的步骤:
1.打开冰箱门
2.把大象装进冰箱
3.关闭冰箱门
*/
// 使用面向过程的方式
po(5,"芭蕾舞");
// 使用面向对象的方式
oo();
}
// 使用面向过程的方式,即一步一步按照步骤来
public static void po(int num,String dance){
// 新需求:转圈,不知道要求转几圈,所以传个参数进来
for (int i = 0; i < num; i++) {
System.out.println("大象已经转第 "+(i+1)+" 圈了");
}
// 新需求:跳舞,不知道要跳什么舞蹈,所以传个参数进来
System.out.println("大象跳个"+dance);
// 第一步:打开冰箱门
System.out.println("打开冰箱门");
// 第二步:把大象装进冰箱
System.out.println("把大象装进冰箱");
// 第三步:关闭冰箱门
System.out.println("关闭冰箱门");
// 到现在为止,完成所有步骤,已经将大象关进冰箱了
// 新需求,将大象关进笼子
// 第一步:打开冰箱门
System.out.println("打开冰箱门");
// 第二步:把大象放出冰箱
System.out.println("把大象放出冰箱");
// 第三步:打开笼子
System.out.println("打开笼子");
// 第四步:把大象装进笼子
System.out.println("把大象装进笼子");
// 第五步:关闭笼门
System.out.println("关闭笼门");
}
// 使用面向对象的方式,即创建一个冰箱对象,让冰箱来打开、装大象、关门,我们只需要调用它的方法就可以了
public static void oo(){
// 实例化一个冰箱对象,让冰箱来完成这些操作
Refrigerator refrigerator=new Refrigerator();
// 新需求:转圈
refrigerator.round(5);
// 新需求:跳舞
refrigerator.dance("芭蕾舞");
// 调用方法,打开冰箱门
refrigerator.open();
// 调用方法,把大象装进冰箱
refrigerator.putElephant();
// 调用方法,关闭冰箱门
refrigerator.close();
// 新需求,将大象关进笼子
// 第一步:打开冰箱门
refrigerator.open();
// 第二步:把大象放出冰箱
refrigerator.putOutElephant();
// 第三步:打开笼子
// 使用到了笼子对象,实例化它
Cage cage=new Cage();
cage.open();
// 第四步:把大象装进笼子
cage.putElephant();
// 第五步:关闭笼门
cage.close();
}
}
/**
* 这是一个笼子类,该类有操作笼子的方法,如打开笼子等
*/
class Cage {
public void open(){
System.out.println("打开笼子");
}
public void putElephant(){
System.out.println("把大象装进笼子");
}
public void close(){
System.out.println("关闭笼门");
}
}
/**
* 这是一个冰箱类,该类有操作冰箱的方法,如打开冰箱门等
*/
class Refrigerator{
public void round(int num){
for (int i = 0; i < num; i++) {
System.out.println("大象已经转第 "+(i+1)+" 圈了");
}
}
public void dance(String dance){
System.out.println("大象跳个"+dance);
}
public void open(){
System.out.println("打开冰箱门");
}
public void putElephant(){
System.out.println("把大象装进冰箱");
}
public void putOutElephant(){
System.out.println("把大象放出冰箱");
}
public void close(){
System.out.println("关闭冰箱门");
}
}
我们敏锐地发现笼子Cage类和冰箱Refrigerator类有相似的地方,比如open()、close()方法,利用面向对象的继承来处理下。
public class Demo {
public static void main(String[] args) {
/*
把大象装进冰箱的步骤:
1.打开冰箱门
2.把大象装进冰箱
3.关闭冰箱门
*/
// 使用面向过程的方式
po();
// 使用面向对象的方式
oo();
}
// 使用面向过程的方式,即一步一步按照步骤来
public static void po() {
// 第一步:打开冰箱门
System.out.println("打开冰箱门");
// 第二步:把大象装进冰箱
System.out.println("把大象装进冰箱");
// 第三步:关闭冰箱门
System.out.println("关闭冰箱门");
// 到现在为止,完成所有步骤,已经将大象关进冰箱了
// 新需求,将大象关进笼子
// 第一步:打开冰箱门
System.out.println("打开冰箱门");
// 第二步:把大象放出冰箱
System.out.println("把大象放出冰箱");
// 第三步:打开笼子
System.out.println("打开笼子");
// 第四步:把大象装进笼子
System.out.println("把大象装进笼子");
// 第五步:关闭笼门
System.out.println("关闭笼门");
}
// 使用面向对象的方式,即创建一个冰箱对象,让冰箱来打开、装大象、关门,我们只需要调用它的方法就可以了
public static void oo() {
// 实例化一个冰箱对象,让冰箱来完成这些操作
Refrigerator refrigerator = new Refrigerator();
// 调用方法,打开冰箱门
refrigerator.open();
// 调用方法,把大象装进冰箱
refrigerator.putInto("大象");
// 调用方法,关闭冰箱门
refrigerator.close();
// 新需求,将大象关进笼子
// 第一步:打开冰箱门
refrigerator.open();
// 第二步:把大象放出冰箱
refrigerator.putOut("大象");
// 第三步:打开笼子
// 使用到了笼子对象,实例化它
Cage cage = new Cage();
cage.open();
// 第四步:把大象装进笼子
cage.putInto("大象");
// 第五步:关闭笼门
cage.close();
}
}
/**
* 创建一个容器类,该类有操作容器的通用方法,如打开、关闭等
*/
class Container {
private String containerName;
public Container() {
}
public Container(String containerName) {
this.containerName = containerName;
}
public void open() {
System.out.println("打开" + this.containerName);
}
public void putInto(Object obj) {
System.out.println("把" + obj + "装进" + this.containerName);
}
public void putOut(Object obj) {
System.out.println("把" + obj + "放出" + this.containerName);
}
public void close() {
System.out.println("关闭" + this.containerName);
}
}
/**
* 这是一个笼子类,该类有操作笼子的方法,如打开笼子等
*/
class Cage extends Container {
Cage() {
super("笼子");
}
}
/**
* 这是一个冰箱类,该类有操作冰箱的方法,如打开冰箱门等
*/
class Refrigerator extends Container {
Refrigerator() {
super("冰箱");
}
}
现在冰箱有个特殊的功能,就是要它制冷,直接在冰箱Refrigerator类中添加该方法就可以了
/**
* 这是一个冰箱类,该类有操作冰箱的方法,如打开冰箱门等
*/
class Refrigerator extends Container {
Refrigerator() {
super("冰箱");
}
public void freeze(){
System.out.println("制冷");
}
}
其实看到这儿,就明白了,面向对象的可扩展性、复用性、维护性更佳。
可扩展性体现:面向过程如果要添加某个功能,就需要在该方法内的合适位置,写该功能的逻辑代码;而面向对象,只需要在该对象中添加一个实现功能的逻辑方法即可,然后让该对象调用就可以了,如果有很多新需求新功能,都可以在对应对象添加方法来实现,而面向过程需要把所有步骤集中在一起。
可复用性体现:面向过程,在开发中有个功能以前写过相同或相似的,然后需要找到那个使用了该功能的代码段,将那一段代码全部复制过来,再根据需求修改,说实话很麻烦的;而面向对象只需要将那个类文件拖过来,继承也好,封装也罢,方便得多,而且可以将其封装成jar包,引入调用功能即可。
可维护性:面向过程,如果要删除某个功能,那么就要将相关的代码注释掉或删除掉,如果代码很多,涉及变量很多,那么非常麻烦;而面向对象将调用的方法注释掉及相关代码注释,要少得多。
说这些的目的不是说面向对象就比面向过程优秀,对于程序员来说,无论面向对象还是面向过程,只有适合和不适合的说法,如果某个需求场景适合面向过程就使用面向过程,如果适合面向对象就使用面向对象,而不用纠结到底使用那个,喜欢就好。
而且在某些方面,如性能,面向过程就表现得更好。