日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > 公眾號精選 > 架構師社區(qū)
[導讀]“我是舊時代的殘黨,新時代沒有承載我的船?!比绻嫦?qū)ο缶幊淌且粋€人,我猜他自己在不斷被非議的今天,一定會這樣感慨。說實話,我用面向?qū)ο蠓绞骄幊桃呀?jīng)十幾年了,我做架構設計離不開它,做系統(tǒng)分析離不開它,編碼的時候更是嚴重依賴它,我對面向?qū)ο鬅o論是思想上還是寫代碼上都對它是有很深的感...

“我是舊時代的殘黨,新時代沒有承載我的船?!?/p>如果面向?qū)ο缶幊?/a>是一個人,我猜他自己在不斷被非議的今天,一定會這樣感慨。

說實話,我用面向?qū)ο蠓绞骄幊桃呀?jīng)十幾年了,我做架構設計離不開它,做系統(tǒng)分析離不開它,編碼的時候更是嚴重依賴它,我對面向?qū)ο鬅o論是思想上還是寫代碼上都對它是有很深的感情。

剛學 Java 的時候,我覺得面向?qū)ο缶幊蹋∣OP)真牛逼,用面向?qū)ο蠓绞綄懗鰜淼拇a是最好的代碼。但是隨著項目越做越多,代碼越寫越多,我發(fā)現(xiàn) OOP 不是萬能的,盲目的迷信追求 OOP 會有代價。

今天這篇文章我不是說面向?qū)ο蟛缓?,只是希望大家不要過度神話它,更不要人云亦云。

大家都聽說過

面向?qū)ο蟮娜筇匦裕豪^承、封裝、多態(tài)

但其實這個說法有問題。面向?qū)ο蟮乃枷肜餂]有任何繼承和多態(tài)的概念,正確的說法是:

這三大特性是面向?qū)ο笳Z言的特性,而不是面向?qū)ο罄砟畋旧淼摹?/p>面向?qū)ο笳Z言是面向?qū)ο笤O計思想的一種實現(xiàn),面向?qū)ο笳Z言為了能在真實世界使用,其必須經(jīng)過一些拓展和妥協(xié),而問題也就隨著這些拓展和妥協(xié)而來。

1. 繼承帶來的也可能是無以復加的痛苦

在實際開發(fā)中,我們無論誰寫代碼,都要考慮代碼的復用性。面向?qū)ο蟮木幊陶Z言作為給開發(fā)人員使用的工具,它也必須考慮到復用性。

所以,在面向?qū)ο缶幊陶Z言里,對面向?qū)ο蟮幕A思想做了拓展,搞出了繼承這個概念。

繼承就具體實現(xiàn)來說,就是子類擁有父類的所有非 private 的屬性和方法。繼承的出現(xiàn)能夠最大化的代碼復用。

當項目里一個類已經(jīng)有了我們需要的屬性和方法,而我們現(xiàn)在的需求只是在這個已有類的基礎上有些許的不同,我們只需要繼承這個類,僅把這少許的不同在子類中實現(xiàn)即可。

但是如果你用了繼承,你就引入了問題。

繼承的出現(xiàn)天然會使得子類和父類緊耦合。也就是說,父類和子類是緊密關聯(lián)的,牽一發(fā)動全身。

如果現(xiàn)實世界里,所有業(yè)務模型都是有層次的,而且層次井然有序,是一顆天然的樹,那這種緊耦合沒有什么問題。

但是現(xiàn)實的需求可不是吃干飯的!

咱們看看這樣一種情況。假設現(xiàn)在我們一家只有兩口人,即只有父親和孩子,那么類繼承模型很容易模擬這種情況:

我們在現(xiàn)實生活里,往往是三口之家:

那這就有問題了。就像小時候經(jīng)常有人會問孩子,你覺得你是爸爸的孩子,還是媽媽的孩子???如果你要用 Java 的規(guī)矩回答,只能從是爸爸或者媽媽里選一個,那么完蛋了?;卮鸢职值暮⒆?,媽媽不高興;回答媽媽的孩子,問題更嚴重,隔壁老王?

但是,如果像 C 那樣,你說我既是爸爸的孩子也是媽媽的孩子,也有問題。

假設爸爸類里有個方法叫說話,媽媽類也有個方法叫說話,你作為繼承了他們的孩子類,自然也會擁有說話這個方法。問題來了,你所擁有的的說話這個方法到底來源于誰?

另外咱們說了,繼承會把子類和父類緊耦合,一旦業(yè)務模型失配,就會造成問題。

這里給出一個維基百科舉的經(jīng)典例子,來說明一下:

class?Super?{

??private?int?counter?=?0;

??void?inc1()?{
????counter ;
??}

??void?inc2()?{
????counter ;
??}

}

class?Sub?extends?Super?{

??@Override
??void?inc2()?{
????inc1();
??}

}
你看,子類覆蓋了父類的 inc2 方法,但是這個 inc2 方法依賴于父類 inc1 的實現(xiàn)。

如果父類的 inc1 邏輯發(fā)生變化了,變成下面這樣

class?Super?{

??private?int?counter?=?0;

??void?inc1()?{
????inc2();
??}

??void?inc2()?{
????counter ;
??}
}
這就會出現(xiàn) stack overflow 的異常,因為出現(xiàn)了無限遞歸。

所以,當我們在子類里,依賴了父類方法作為子類業(yè)務邏輯的一個關鍵步驟的時候,當父類的邏輯修改的時候,必須聯(lián)動修改所有依賴父類相關邏輯的子類,否則就可能引發(fā)嚴重的問題。

用繼承,本來是想少寫點代碼少加點班,結(jié)果……用網(wǎng)上看到的一句話說就是:

一日為父,終生是祖宗。

像這種情況該怎么辦?

現(xiàn)在只要是個正經(jīng)的介紹面向?qū)ο蟮募夹g文章或者書籍里,只要是涉及到繼承的,都會加這么句話:

盡量選擇對象組合的設計方式。

在《阿里巴巴Java開發(fā)手冊》中就有一條:

組合和繼承的區(qū)別如下:

其實我認為繼承和組合各有優(yōu)缺點,如果兩個類確實非常緊密,就是存在層次關系,用繼承沒問題。

之所以有“組合優(yōu)于繼承”這個說法,我個人感覺是組合更靈活,而且能防止被人濫用,用不好的話輕則類的層次失控,重則很可能就把整個項目的代碼質(zhì)量給腐蝕了。

2. 封裝如同帶有漏洞的封印,可能會逃逸出魔王

封裝,說白了就是把屬性、方法,封到一個對象里,這是面向?qū)ο蟮暮诵睦砟睢?/p>嘴上叫封裝,卻開了個縫兒。

我們知道,項目是既要兼顧代碼質(zhì)量,還要兼顧運行性能的。不可能說為了提升什么松耦合、高內(nèi)聚,就不管不顧性能了。

事情就壞在了這個兼顧性能這里。面向?qū)ο罄?,以上帝角度看,系統(tǒng)就是對象和對象之間的關系構造成的網(wǎng)絡。

就拿咱們上面談到的組合關系來說,組合關系的實現(xiàn)就是通過把一個對象當成另一個對象的屬性來實現(xiàn)的。

上面這圖就叫做 A 和 B 之間是組合關系。想用 A 對象里的 B 對象,代碼這么寫:

A?a?=?new?A();
B?b?=?a.getB();
好,我們要問了,這個從 A 中獲取的 B,是 B 對象的實例還是實例的一個引用指針呢?

必然是引用指針吧,這是最基礎的知識。諾,問題來了,引用指針是可以修改的。

b.getS();?//原來是Hello?World
b.setS("World");//直接改成World
原來 B 中有個字段 s,值是個 “Hello World”,我直接可以用代碼改成“World”。

如果這次修改隨意在個犄角旮旯里,A 能知道嗎?A 蒙在鼓里,還以為一切盡在把控當中呢。

你看,封裝的縫兒出來了吧。說句實話,就這種鬼操作,是非常難以排查的。

像這種封裝了,但是又沒封裝的問題,我只想說“封裝的挺好的,下次別封裝了”。

3. 多態(tài)好,但可能是面向?qū)ο蟮呢澨熘?/h2>再說說多態(tài)。

其實,面向?qū)ο笾械亩鄳B(tài)使用,才是面向?qū)ο笳Z言最被認可的地方。因為有了多態(tài),代碼才能保證在業(yè)務需求多變的情況下,保證了項目的相對穩(wěn)定。

可是,多態(tài)不是面向?qū)ο螵氂械陌?。面向過程,函數(shù)式編程也可以:面向過程里,C 語言可以靠虛函數(shù)去在運行時加載對應的函數(shù)實現(xiàn)去實現(xiàn)多態(tài)。函數(shù)式編程也可以通過組合函數(shù)去實現(xiàn)多態(tài)。

所以,面向?qū)ο筮B多態(tài)這種優(yōu)勢都不獨特了。

4. 服務端業(yè)務變了,人們的觀點發(fā)生變化了

在說服務端業(yè)務的變化之前,我想先普及兩個概念,即有狀態(tài)的服務和無狀態(tài)的服務。

有狀態(tài)的服務就是說,服務需要暫時存一些和客戶端相關的數(shù)據(jù),以便客戶端后續(xù)發(fā)來的請求可以和客戶端前面發(fā)的請求通過服務器端關聯(lián)起來,從而共同完成一項業(yè)務。

無狀態(tài)服務是說,服務端不存儲任何和客戶端相關的數(shù)據(jù),客戶端每次請求,服務端都認為這是個新客戶端,和以前的請求無任何關系。

用現(xiàn)實生活舉例的話,有狀態(tài)服務就是你去一家健身房,第一次去的時候花了一筆錢辦了一張健身卡,你以后每次去健身,有卡就不用再掏錢了。

無狀態(tài)服務就是,你沒辦卡,每次去都和第一次去一樣現(xiàn)掏錢。

那么,無狀態(tài)服務和有狀態(tài)服務和面向?qū)ο蟮乃ヂ溆钟惺裁搓P系呢?在如今的年代,分布式、微服務大行其道。一個有狀態(tài)的服務是不容易做分布式和做彈性伸縮的。

當年,大家做有多個步驟的業(yè)務的時候,為了保證業(yè)務數(shù)據(jù)不會因為用戶偶然的關閉瀏覽器或者瀏覽器崩潰等問題而丟失,往往會把上一個步驟的信息存在服務端的 session 里,而現(xiàn)在則會傾向考慮把信息放在客戶端的本地存儲上。

我舉個例子,假設現(xiàn)在有個需求,要在后臺系統(tǒng)新增加一個功能:用戶信息管理。其中有個需求要求這樣操作,錄入用戶信息分成兩步。

  • 第一步,錄入用戶的基本信息:姓名、手機號、年齡……

  • 第二步,錄入額外信息:家庭成員、教育經(jīng)歷、工作經(jīng)歷……

出于信息完整度的考慮,業(yè)務要求這兩步應該是一個完整的事務。要么都成功,要么都失敗。

從技術實現(xiàn)上講,如果是多年以前,我們會在第一步的時候,把商戶的基本信息做成表單提交,然后為了保證不會因為用戶誤關閉瀏覽器等意外問題丟失中間的數(shù)據(jù),保存在對應的 session 中后,在第二步信息提交后,合并起來一起存入到數(shù)據(jù)庫中。

但是,現(xiàn)在的技術趨勢是,做任何事情,盡量讓服務器端無狀態(tài),也就是不存儲客戶端相關數(shù)據(jù)。

此時,這個需求的解決方案就是,當?shù)谝徊教顚懮虘粜畔⑼瓿珊?,直接把?shù)據(jù)存儲在客戶端的本地存儲里又或者直接就存在 cookie 里,在第二步填寫內(nèi)容完畢后,聯(lián)合存在客戶端的信息一起提交到服務器端,然后存入數(shù)據(jù)庫。

所以,你看到了,現(xiàn)在大家的趨勢就是服務器端都在轉(zhuǎn)向無狀態(tài)服務,哪怕以前是有狀態(tài)的服務,也會通過一些增加客戶端參數(shù)等手段,去改造為無狀態(tài)服務。

說了這么多,那這種技術趨勢的變化對我們的面向?qū)ο笥惺裁从绊懩兀?/p>影響在于,服務端現(xiàn)在越來越變得往單純的處理數(shù)據(jù)這個方向發(fā)展。當僅處理數(shù)據(jù)的時候,服務器端真正的需求其實就是計算,然后就是為了大幅度提升計算速度,而帶來的并行化需求。

而面向?qū)ο筮@種方式和我們當今的技術趨勢是有一些沖突的。

首先就是確定性的沖突。

我們的首要需求從以前重度處理業(yè)務狀態(tài)加業(yè)務數(shù)據(jù)變成了業(yè)務數(shù)據(jù)的計算,而計算是需要確定性的:即給定相同的輸入,經(jīng)過服務器端相同的邏輯處理后,應該給定相同的輸出。

而面向?qū)ο筮@種方式,出身在有狀態(tài)服務大行其道的年代,它會優(yōu)先考慮業(yè)務邏輯的調(diào)度,其次才是計算,所以,面向?qū)ο笫菗碛袪顟B(tài)的。面向?qū)ο蟮臓顟B(tài)就是它的字段值。這些字段值,如果單純的從計算數(shù)據(jù)角度看,他們不僅無意義了,反而還引入了風險。

比如,我們不小心把一個對象的狀態(tài)給共享出去了,那當我們用同樣的輸入計算的時候,很可能由于狀態(tài)的變化,導致了不同的輸出結(jié)果,最后就是項目出了問題。

其次,由于計算我們對性能更加看重了,又由于無狀態(tài)服務的大量使用,所以,并行的重要性也遠遠超出了以前。而并行,要求的是結(jié)構的開放,和更加嚴格的無狀態(tài)化,而面向?qū)ο螅∏乐匾蕾囉跔顟B(tài),并且,他還把這種狀態(tài)依賴封裝在了復雜的對象關系里。

A 狀態(tài)依賴于 B 的狀態(tài),B 的狀態(tài)又依賴于 C,而這些依賴,全部被封裝在了 D 對象的實現(xiàn)細節(jié)里,這種嚴重的反并行也是現(xiàn)在越來越多人開始反感面向?qū)ο蟮闹匾颉?/p>

結(jié)尾

說了這么多面向?qū)ο蟮膲脑?,其實真的是面向?qū)ο笞陨淼膯栴}嗎?并不是。

首先,面向?qū)ο笃鋵嵕褪俏覀兂绦騿T試圖簡化這個世界,提高對這個世界的認知的一種美好愿望而已。愿望來自于人自身認知的局限性,所以本身就不可能完美。

其次,
面向?qū)ο缶幊?/a>語言只是一種工具,工具的使用的好壞還是要靠人的,不可能每個人能把一套工具用的完美無缺。

如上所說,面向?qū)ο蟮膯栴}本質(zhì)還是人的問題,而人可能永遠都需要通過組合使用越來越多的類似面向?qū)ο蟮倪@種并不完美的工具去解決自己的問題。

所以,我們不能一味的依靠面向?qū)ο?,認為面向?qū)ο缶褪亲畎舻?,也不能發(fā)現(xiàn)面向?qū)ο罂赡軕恫涣四承I(yè)務場景了,就開始極端地摒棄它。

我們要靈活地,合理地使用任何我們可以使用的編程思想、編程工具,積極地去擁抱變化。

不要忘了我們寫代碼的初衷。

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

電感是導線內(nèi)通過交流電流時,在導線的內(nèi)部及其周圍產(chǎn)生交變磁通,導線的磁通量與生產(chǎn)此磁通的電流之比。電感器也叫電感線圈,是利用電磁感應原理制成的,由導線在絕緣管上單層或多層繞制而成的,導線彼此互相絕緣,而絕緣管可以是空心的...

關鍵字: 電感 磁通量 電感器

根據(jù)交通運輸部水運科學研究院提出的智慧港口的概念,智慧港口是利用新一代信息技術,將港口相關業(yè)務和管理創(chuàng)新深度融合,使港口更加集約、高效、便捷、安全、綠色,創(chuàng)新港口發(fā)展模式,實現(xiàn)港口科學可持續(xù)發(fā)展。

關鍵字: 智慧港口 信息技術 業(yè)務

近年來,世界主要汽車大國紛紛加強新能源汽車戰(zhàn)略謀劃、強化政策支持、完善產(chǎn)業(yè)布局,新能源汽車已成為全球汽車產(chǎn)業(yè)轉(zhuǎn)型發(fā)展的主要方向和促進世界經(jīng)濟持續(xù)增長的重要引擎。2021年,全國新能源汽車實現(xiàn)產(chǎn)量354.5萬輛,銷量352...

關鍵字: 新能源 汽車 引擎

2007-2021年,全球針狀焦行業(yè)專利申請人數(shù)量及專利申請量總體呈現(xiàn)增長態(tài)勢。雖然2021年全球針狀焦行業(yè)專利申請人數(shù)量及專利申請量有所下降,但是這兩大指標數(shù)量仍較多。整體來看,全球針狀焦技術處于成長期。

關鍵字: 針狀焦行業(yè) 專利申請人 增長態(tài)勢

按企業(yè)主營業(yè)務類型分,我國智能家居行業(yè)競爭派系可分為傳統(tǒng)家電企業(yè)、互聯(lián)網(wǎng)企業(yè)以及其他企業(yè)三派。傳統(tǒng)家電企業(yè)代表有海爾智家、美的集團、格力電器等,具有供應鏈和銷售渠道,制造能力和品牌優(yōu)勢突出;互聯(lián)網(wǎng)企業(yè)代表有小米集團、百度...

關鍵字: 智能家居 互聯(lián)網(wǎng)企業(yè) 供應鏈

軍工電子是集紅外技術、激光技術、半導體及嵌入式技術與虛擬仿真技術為一體的綜合性軍工技術體系,是國防信息化建設的基石。軍工電子行業(yè)包含在軍工行業(yè)內(nèi),專注于軍工行業(yè)電子產(chǎn)品布局。根據(jù)其軍工產(chǎn)品的不同可分為衛(wèi)星導航、通信指揮、...

關鍵字: 軍工電子 嵌入式技術 信息化建設

我國汽車零配件行業(yè)細分種類眾多,從汽車零配件主要產(chǎn)品來看,發(fā)動機系統(tǒng)行業(yè)內(nèi)有濰柴動力、華域汽車等主要從業(yè)企業(yè);在車身零部件領域內(nèi),福耀玻璃、中策橡膠具有一定的規(guī)模優(yōu)勢;行駛系統(tǒng)領域內(nèi)有中策橡膠提供的輪胎以及華為等企業(yè)提供...

關鍵字: 汽車零配件 發(fā)動機 行駛系統(tǒng)

茶飲料是指以茶葉或茶葉的水提取液、濃縮液、茶粉(包括速溶茶粉、研磨茶粉)或直接以茶的鮮葉為原料添加或不添加食品原輔料和(或)食品添加劑,經(jīng)加工制成的液體飲料。根據(jù)國家標準《茶飲料(GB/T 21733-2008)》的規(guī)定...

關鍵字: 茶飲料 茶葉的水 食品添加劑

全球液壓行業(yè)專利技術在21世紀初得到初步發(fā)展,這一時期液壓專利申請人數(shù)量和申請量處于較低水平。2011-2012年,液壓行業(yè)專利技術的發(fā)展總體處于成長期,2012年以后中全球液壓行業(yè)專利技術申請量或申請人數(shù)量整體處于波動...

關鍵字: 液壓行業(yè) 專利授權 技術類型

從上市企業(yè)的總市值情況來看,2022年7月28日,中芯國際、紫光國微和韋爾股份總市值遙遙領先,中芯國際總市值達到3238.21億元,紫光國微總市值達到1358.77億元,韋爾股份總市值達到1277.07億元;其次是兆易創(chuàng)...

關鍵字: 上市企業(yè) 集成電路 行業(yè)

架構師社區(qū)

1736 篇文章

關注

發(fā)布文章

編輯精選

技術子站

關閉