面向對象編程?你說的是看着女朋友進行編程嗎?
注釋:沒有對象怎辦?
前幾天網上看到一個有趣的面試問題:
農場有頭大母牛,每年生頭小母牛,小母牛五年后生小母牛,年齡大於15便死亡💀,問20年后農場一共有多少頭牛?(使用面向對象編程思維解答)
這個面試問題讓我想到了面向過程與面向對象編程的區別,咱們先簡單了解下這兩者定義上區別:
- 面向過程 就是分析出解決問題所需要的步驟,然后用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就可以了。
- 面向對象 是把構成問題事務分解成各個對象,建立對象的目的不是為了完成一個步驟,而是為了描敘某個事物在整個解決問題的步驟中的行為。
看了定義,是不是感覺還是沒明白這兩者之間的區別,(我信你個鬼,糟老頭子壞的很),
那咱們就用圖片來作下對比吧:
然后我就寫了兩套代碼來作對比,一套是面向過程編程,一套是面向對象編程。咱們一起來看看這兩者這間到底有何區別?
面向過程:
public static void main(String[] args){ //所有牛的集合 List<Integer> cowAgeList = new ArrayList<>(); //添加第一只5歲的大母牛 cowAgeList.add(5); //循環20年 for(int i=0;i<20;i++){ int count_new = 0;//當年新生數量 int count_dead = 0;//當年死亡數量 //當年新生的集合 List<Integer> cowChild = new ArrayList<>(); //遍歷當年所有母牛,年齡自增、看看生不生 for(int index=0;index<cowAgeList.size();index++){ //新的一年,加一歲 int age = cowAgeList.get(index) + 1; //將新年齡設置回集合中 cowAgeList.set(index,age); //看下這頭母牛是否該GameOver了 if(age>15){ count_dead++; continue; } //試下生只小母牛吧,生不生的出來說不准(看年齡) Integer cowNew = produce(age); //哎,如果還生出來了,那咱們就挪窩到當年新生牛犢(不是牛肚哈)集合中 if(cowNew!=null){ count_new++; //這里有個小細節,容易出錯,我開始就想,直接把新生小母牛放到所有牛集合中不就行了, //為啥非得先放到當年新生小母牛集合中,后面再統一放到所有牛集合中,你先想下這個問題 //咱們后面再說為什么需要這么做 cowChild.add(cowNew); } } //今年生牛這個過程結束了,然后再把新生小母牛都放到所有牛集合中 cowAgeList.addAll(cowChild); //我們上面說到為什么不直接把新生的小母牛直接放到所有牛集合中 //因為如果把新新生小母牛直接放到所有牛集合中, // 那么當年這個新生的小母牛就會在后面的遍歷中再次遍歷一次 //新生的小母牛年齡是0吧,直接放到所有牛集合中, // 新生小母牛年齡就也自增了,這不是我們想要的 System.out.println(String.format("第%d年,出生:%d,死亡:%s",i,count_new,count_dead)); } //使用迭代器移除已經死亡的母牛,剩下的就是20年后所有存活的母牛了 Iterator<Integer> iterator = cowAgeList.iterator(); while(iterator.hasNext()){ if(iterator.next().intValue()>15){ iterator.remove(); } } System.out.println(String.format("20年后農場存活牛的數量為:%d",cowAgeList.size())); } /** * 根據母牛年齡生產小母牛 * @param age-母牛年齡 * @return 新生小牛年齡(null表示沒有生) */ private static Integer produce(int age){ if(age>=5 && age<=15){ return 0; } return null; }
面向對象:
牛的對象:
/** * 這是頭牛 * * @Date: 2019/7/26 */ public class Cow { /** * 年齡 */ private int age; /** * 是否活者 */ private boolean alive = true; public Cow(int age) { this.age = age; } /** * 生牛動作 * 是否能生的出來,得看年齡 * * @return */ public Cow produceCow() { if (this.age < 5 || !this.isAlive()) { return null; } return new Cow(0); } /** * 每年長一歲 */ public void addAge() { this.age += 1; //年齡大於15就掛掉 if (this.age > 15) { this.alive = false; } } public boolean isAlive() { return alive; } }
農場對象:
import java.util.ArrayList; import java.util.List; /** * 這就是一個農場 * * @Date: 2019/7/26 */ public class Farm { //農場里所有牛的集合 private List<Cow> cowList = new ArrayList<>(); public Farm() { } public List<Cow> getCowList() { return cowList; } public void setCowList(List<Cow> cowList) { this.cowList = cowList; } }
上帝角色(主宰一切):
import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * 微信關注[Java知己],每天更新技術干貨 * 發送「1024」,免費領取 30 本經典編程書籍。 * 發送「Group」,與 10 萬程序員一起進步。 * 發送「JavaEE實戰」,領取《JavaEE實戰》系列視頻教程。 * 發送「玩轉算法」,領取《玩轉算法》系列視頻教程。 */ public class Main { /** * 這里是上帝角色,控制着一切 * @param args */ public static void main(String[] args) { //實例化農場 Farm farm = new Farm(); //實例出來第一頭母牛 Cow cow = new Cow(5); //將第一只牛放到農場里面 farm.getCowList().add(cow); for(int year=0;year<20;year++){ int count_dead = 0;//死亡數量 List<Cow> cowChilds = new ArrayList<>(); for(Cow cowTemp:farm.getCowList()){ cowTemp.addAge(); Cow child = cowTemp.produceCow(); if(child!=null){ cowChilds.add(child); } if(!cowTemp.isAlive()){ count_dead++; } } farm.getCowList().addAll(cowChilds); System.out.println(String.format("第%d年,出生:%d,死亡:%d",year,cowChilds.size(),count_dead)); } //移除已經死亡的牛 Iterator<Cow> iterator = farm.getCowList().iterator(); while(iterator.hasNext()){ if(!iterator.next().isAlive()){ iterator.remove(); } } System.out.println(String.format("20年后農場存活牛的數量為:%d",farm.getCowList().size())); } }
下面是運行結果:(兩種方式的運行結果是一致的)
第0年,出生:1,死亡:0 第1年,出生:1,死亡:0 第2年,出生:1,死亡:0 第3年,出生:1,死亡:0 第4年,出生:1,死亡:0 第5年,出生:2,死亡:0 第6年,出生:3,死亡:0 第7年,出生:4,死亡:0 第8年,出生:5,死亡:0 第9年,出生:6,死亡:0 第10年,出生:7,死亡:1 第11年,出生:10,死亡:1 第12年,出生:14,死亡:1 第13年,出生:19,死亡:1 第14年,出生:25,死亡:1 第15年,出生:32,死亡:1 第16年,出生:41,死亡:2 第17年,出生:54,死亡:3 第18年,出生:72,死亡:4 第19年,出生:96,死亡:5 20年后農場存活牛的數量為:391
咱們通過代碼演示,你感覺到這兩者的區別了嗎?
面向對象編程對於勻我們來說更容易理解業務的邏輯性
就算是自己寫的代碼,過上一段時間,自己再去看,是不是也是一頭霧水,得好好看上一段時間才能理得清楚某塊代碼的業務邏輯是怎樣的
用下面這張圖來形容,偶然間看到自己多年前寫的代碼,我覺得很貼合實際
注釋:偶然間看到自己多年前寫的代碼
結論:面向對象思維可以提升項目的可維護性
最后讓我們做下總結:
面向過程
優點:性能比面向對象高,因為類調用時需要實例化,開銷比較大,比較消耗資源;比如單片機、嵌入式開發、 Linux/Unix等一般采用面向過程開發,性能是最重要的因素。
缺點:沒有面向對象易維護、易復用、易擴展
面向對象
優點:易維護、易復用、易擴展,由於面向對象有封裝、繼承、多態性的特性,可以設計出低耦合的系統,使系統 更加靈活、更加易於維護
缺點:性能比面向過程低
正是金九銀十跳槽季,為大家收集了2019年最新的面試資料,有文檔、有攻略、有視頻。有需要的同學可以在公眾號【Java知己】,發送【1024】領取30本Java經典開發書籍,發送【面試】領取最新面試資料攻略!