面向过程 VS 面向对象
面向過程(Process Oriented)這個(gè)詞是在面向?qū)ο?#xff08;Object Oriented)出現(xiàn)之后為與之相對(duì)而提出的。其實(shí)它在以前基本被叫做“結(jié)構(gòu)化編程”。
???????早期的程序設(shè)計(jì),大量使用共享變量(全局變量)和GOTO語句一類的東西,后來有人證明所有有意義的程序流程都可以使用三種基本流程(順序、選擇、重復(fù))來實(shí)現(xiàn),并提出“GOTO有害說”,從此人們進(jìn)行編程的方式發(fā)生重大變化,每種語言都提供這些基本控制結(jié)構(gòu)的實(shí)現(xiàn)方式,并提供把數(shù)據(jù)訪問局部化的能力,以及某種形式的模塊化/分別編譯機(jī)制。在這些基礎(chǔ)上,人們所進(jìn)行的編程活動(dòng)基本是通過寫用于不同目的的功能函數(shù)/過程來實(shí)現(xiàn),故稱為“面向過程”。
?????
????? ? 面向過程開發(fā)方式是對(duì)計(jì)算機(jī)底層結(jié)構(gòu)的一層抽象,它明顯把程序的內(nèi)容分為數(shù)據(jù)和操縱數(shù)據(jù)的操作兩部分。這種編程方式的核心問題是數(shù)據(jù)結(jié)構(gòu)和算法的開發(fā)和優(yōu)化。C 語言所提供的機(jī)制就是典型的結(jié)構(gòu)化編程設(shè)施。
???????面向?qū)ο?/strong>是繼結(jié)構(gòu)化革命之后的又一次軟件開發(fā)方式革命。面向?qū)ο蟮闹饕枷胧腔?strong>抽象數(shù)據(jù)類型的(Abstract Data Type, ADT):在結(jié)構(gòu)化編程過程中,人們發(fā)現(xiàn)把某種數(shù)據(jù)結(jié)構(gòu)和用于操縱它的各種操作以某種模塊化方式綁定到一起會(huì)非常方便,使用這種方式進(jìn)行編程時(shí)數(shù)據(jù)結(jié)構(gòu)的接口是固定的。
???? 如果對(duì)抽象數(shù)據(jù)類型進(jìn)一步抽象,就會(huì)發(fā)現(xiàn)把這種數(shù)據(jù)類型的實(shí)例當(dāng)作一個(gè)具體的東西、事物、對(duì)象,就可以引發(fā)人們對(duì)編程過程中怎樣看待所處理的問題的一次大的改變。抽象數(shù)據(jù)類型方法雖然也有一定的抽象能力,但其核心仍然是數(shù)據(jù)結(jié)構(gòu)和算法。而面向?qū)ο蠓椒ㄖ苯?strong>把所有事物都當(dāng)作獨(dú)立的對(duì)象,處理問題過程中所思考的不再主要是怎樣用數(shù)據(jù)結(jié)構(gòu)來描述問題,而是直接考慮重現(xiàn)問題中各個(gè)對(duì)象之間的關(guān)系。可以說,面向?qū)ο蟾锩淖钪匾獌r(jià)值就在于改變了人們看待和處理問題的方式。
???? 面向?qū)ο蠓椒ㄖ?#xff0c;對(duì)象可以接受其他對(duì)象傳來的消息,也可以向其他對(duì)象發(fā)送消息。有的語言靜態(tài)類型,決定了對(duì)象可接受的消息的范圍,這稱為對(duì)象的類型的接口。有的語言中對(duì)象可以接受任何消息,但只對(duì)其有意義的消息進(jìn)行反應(yīng)。對(duì)象中可以包含其他對(duì)象,這成為“聚合”,對(duì)象可以被當(dāng)作其他類型的對(duì)象,這要求對(duì)象的類型“繼承”另外的類型。對(duì)象只能通過其所提供的接口來進(jìn)行訪問,其內(nèi)部具體實(shí)現(xiàn)是不可訪問的,這成為“封裝”。面向?qū)ο蠓椒ǖ娜齻€(gè)核心要素是:封裝、繼承、多態(tài)。
??
? ? C和C++都可以進(jìn)行面向過程和面向?qū)ο蟮木幊?#xff0c;不同的是C++對(duì)面向?qū)ο笾苯犹峁┱Z言支持,而C中只能通過傳統(tǒng)方式手動(dòng)操作對(duì)象來模擬對(duì)象行為。C++是多模式、多范式的編程語言,它還可以進(jìn)行泛型編程。
???
????Java是一門面向?qū)ο蟮恼Z言,那對(duì)面向?qū)ο蠛兔嫦蜻^程不是很清楚的請(qǐng)看看下面的內(nèi)容,說不定對(duì)你有幫助:
????面向過程就是分析出解決問題所需要的步驟,然后用函數(shù)把這些步驟一步一步實(shí)現(xiàn),使用的時(shí)候一個(gè)一個(gè)依次調(diào)用就可以了。
????面向?qū)ο?/strong>是把構(gòu)成問題事務(wù)分解成各個(gè)對(duì)象,建立對(duì)象的目的不是為了完成一個(gè)步驟,而是為了描敘某個(gè)事物在整個(gè)解決問題的步驟中的行為。
?
例如五子棋:
面向過程的設(shè)計(jì)思路就是首先分析問題的步驟:
1、開始游戲,
2、黑子先走,
3、繪制畫面,
4、判斷輸贏,
5、輪到白子,
6、繪制畫面,
7、判斷輸贏,
8、返回步驟2,
9、輸出最后結(jié)果。
把上面每個(gè)步驟用分別的函數(shù)來實(shí)現(xiàn),問題就解決了。
?
面向?qū)ο?/strong>的設(shè)計(jì)則是從另外的思路來解決問題。整個(gè)五子棋可以分為:
1、黑白雙方,這兩方的行為是一模一樣的,
2、棋盤系統(tǒng),負(fù)責(zé)繪制畫面,
3、規(guī)則系統(tǒng),負(fù)責(zé)判定諸如犯規(guī)、輸贏等。
??????? 第一類對(duì)象(玩家對(duì)象)負(fù)責(zé)接受用戶輸入,并告知第二類對(duì)象(棋盤對(duì)象)棋子布局的變化,棋盤對(duì)象接收到了棋子的變化就要負(fù)責(zé)在屏幕上面顯示出這種變化,同時(shí)利用第三類對(duì)象(規(guī)則系統(tǒng))來對(duì)棋局進(jìn)行判定。
?????? 可以明顯地看出,面向?qū)ο笫?strong>以功能來劃分問題,而不是步驟。同樣是繪制棋局,這樣的行為在面向過程的設(shè)計(jì)中分散在了總多步驟中,很可能出現(xiàn)不同的繪制版本,因?yàn)橥ǔTO(shè)計(jì)人員會(huì)考慮到實(shí)際情況進(jìn)行各種各樣的簡(jiǎn)化。而面向?qū)ο蟮脑O(shè)計(jì)中,繪圖只可能在棋盤對(duì)象中出現(xiàn),從而保證了繪圖的統(tǒng)一。
???? 功能上的統(tǒng)一保證了面向?qū)ο笤O(shè)計(jì)的可擴(kuò)展性。比如我要加入悔棋的功能,如果要改動(dòng)面向過程的設(shè)計(jì),那么從輸入到判斷到顯示這一連串的步驟都要改動(dòng),甚至步驟之間的循序都要進(jìn)行大規(guī)模調(diào)整。如果是面向?qū)ο蟮脑?#xff0c;只用改動(dòng)棋盤對(duì)象就行了,棋盤系統(tǒng)保存了黑白雙方的棋譜,簡(jiǎn)單回溯就可以了,而顯示和規(guī)則判斷則不用顧及,同時(shí)整個(gè)對(duì)對(duì)象功能的調(diào)用順序都沒有變化,改動(dòng)只是局部的。
到這里就可以很明顯的看出面向?qū)ο蠛兔嫦蜻^程的區(qū)別所在了。
?
總結(jié):
1.面向過程程序設(shè)計(jì)方法的實(shí)質(zhì)上是從計(jì)算機(jī)處理問題的觀點(diǎn)來進(jìn)行程序設(shè)計(jì)工作:輸入——運(yùn)算——輸出。面向過程程序設(shè)計(jì)者需要變更習(xí)慣的思維方法以貼近計(jì)算機(jī)的內(nèi)部工作機(jī)理。面向過程程序設(shè)計(jì)所具有的流的工作性質(zhì),試圖通過信息流及其轉(zhuǎn)換來認(rèn)識(shí)系統(tǒng),不僅加大了程序設(shè)計(jì)的難度,同時(shí)亦使得程序的可理解性比較差。
面向過程程序設(shè)計(jì)方法中,一種普遍采用的優(yōu)化方法是使用結(jié)構(gòu)化的程序設(shè)計(jì)方法。
面向過程程序設(shè)計(jì)方法一般適宜采用自上而下的設(shè)計(jì)方法。
面向過程程序設(shè)計(jì)方法需要在一開始就全面的,自上而下的設(shè)計(jì)整個(gè)應(yīng)用程序的架構(gòu),因此要求程序設(shè)計(jì)者對(duì)問題域有全面的了解。
面向過程程序設(shè)計(jì)方法很難復(fù)用以前已經(jīng)設(shè)計(jì)完成的軟件。
2.面向?qū)ο?/strong>程序設(shè)計(jì)是一種自下而上的程序設(shè)計(jì)方法,往往從問題的一部分著手,一點(diǎn)一點(diǎn)地構(gòu)建出整個(gè)程序。面向?qū)ο笤O(shè)計(jì)一數(shù)據(jù)為中心,類作為表現(xiàn)數(shù)據(jù)的工具,成為劃分程序的基本單位。
面向?qū)ο笥幸韵聨讉€(gè)重要特點(diǎn):
(1)客觀世界有對(duì)象組成
(2)對(duì)象抽象為類
(3)類與類之間存在繼承關(guān)系
(4)對(duì)象之間通過傳遞消息而彼此聯(lián)系
面向?qū)ο笫且环N思想,符合人們的思考習(xí)慣。面向?qū)ο蟮某霈F(xiàn),讓復(fù)雜的問題簡(jiǎn)單化。面向?qū)ο蟮某霈F(xiàn),讓曾經(jīng)的執(zhí)行者,變成了現(xiàn)在的指揮者。
?
附:
下面簡(jiǎn)單介紹面向?qū)ο笕筇卣?#xff1a;
封裝:
封裝是指將數(shù)據(jù)與具體操作的實(shí)現(xiàn)代碼放在某個(gè)對(duì)象內(nèi)部,使這些代碼的實(shí)現(xiàn)細(xì)節(jié)不被外界發(fā)現(xiàn),外界只能通過接口使用該對(duì)象,而不能通過任何形式修改對(duì)象內(nèi)部實(shí)現(xiàn),正是由于封裝機(jī)制,程序在使用某一對(duì)象時(shí)不需要關(guān)心該對(duì)象的數(shù)據(jù)結(jié)構(gòu)細(xì)節(jié)及實(shí)現(xiàn)操作的方法。使用封裝能隱藏對(duì)象實(shí)現(xiàn)細(xì)節(jié),使代碼更易維護(hù),同時(shí)因?yàn)椴荒苤苯诱{(diào)用、修改對(duì)象內(nèi)部的私有信息,在一定程度上保證了系統(tǒng)安全性。
繼承:
繼承來源于現(xiàn)實(shí)世界,一個(gè)最簡(jiǎn)單的例子就是孩子會(huì)具有父母的一些特征,即每個(gè)孩子都會(huì)繼承父親或者母親的某些特征,當(dāng)然這只是最基本的繼承關(guān)系,現(xiàn)實(shí)世界中還存在著更復(fù)雜的繼承,面向?qū)ο笾允褂美^承機(jī)制主要是用于實(shí)現(xiàn)代碼的復(fù)用多個(gè)類所公用的代碼部分可以只在一個(gè)類中提供,而其他類只需要繼承即可。
多態(tài):
多態(tài)與繼承纖細(xì)緊密,是面向?qū)ο缶幊讨辛硪粋€(gè)突出的特征,所謂的多態(tài)是指在繼承體系中,所有派生類都從基類繼承接口,但由于每個(gè)派生類都是獨(dú)立的實(shí)體,因此在接收同一消息的時(shí)候,可能會(huì)生成不同的響應(yīng)。多態(tài)的作用作為隱藏代碼實(shí)現(xiàn)細(xì)節(jié),使得代碼能夠模塊化;擴(kuò)展代碼模塊,實(shí)現(xiàn)接口重用。簡(jiǎn)單來說:一種行為產(chǎn)生多種效果。
總的來說:封裝可以隱藏實(shí)現(xiàn)細(xì)節(jié)同時(shí)包含私有成員,使得代碼模塊化并增加安全指數(shù);基礎(chǔ)可以擴(kuò)展已存在的模塊,目的是為了代碼重用;多態(tài)則是為了保證:類在繼承和派生的時(shí)候,保證家譜中任何類的實(shí)例被正確調(diào)用,實(shí)現(xiàn)了接口重用。
多態(tài)實(shí)現(xiàn):
實(shí)現(xiàn)多態(tài),有二種方式,覆蓋,重載。
覆蓋,是指子類重新定義父類的虛函數(shù)的做法。
重載,是指允許存在多個(gè)同名函數(shù),而這些函數(shù)的參數(shù)表不同(或許參數(shù)個(gè)數(shù)不同,或許參數(shù)類型不同,或許兩者都不同)。
其實(shí),重載的概念并不屬于“面向?qū)ο缶幊獭?#xff0c;重載的實(shí)現(xiàn)是:編譯器根據(jù)函數(shù)不同的參數(shù)表,對(duì)同名函數(shù)的名稱做修飾,然后這些同名函數(shù)就成了不同的函數(shù)(至少對(duì)于編譯器來說是這樣的)。如,有兩個(gè)同名函數(shù):function func(p:integer):integer;和function func(p:string):integer;。那么編譯器做過修飾后的函數(shù)名稱可能是這樣的:int_func、str_func。對(duì)于這兩個(gè)函數(shù)的調(diào)用,在編譯器間就已經(jīng)確定了,是靜態(tài)的(記住:是靜態(tài))。也就是說,它們的地址在編譯期就綁定了(早綁定),因此,重載和多態(tài)無關(guān)!真正和多態(tài)相關(guān)的是“覆蓋”。當(dāng)子類重新定義了父類的虛函數(shù)后,父類指針根據(jù)賦給它的不同的子類指針,動(dòng)態(tài)(記住:是動(dòng)態(tài)!)的調(diào)用屬于子類的該函數(shù),這樣的函數(shù)調(diào)用在編譯期間是無法確定的(調(diào)用的子類的虛函數(shù)的地址無法給出)。因此,這樣的函數(shù)地址是在運(yùn)行期綁定的(晚綁定)。結(jié)論就是:重載只是一種語言特性,與多態(tài)無關(guān),與面向?qū)ο笠矡o關(guān)。
?
扯到覆蓋和重載了,那就說說函數(shù)重載、覆蓋、隱藏的基本定義吧。
函數(shù)重載:是指允許存在多個(gè)同名函數(shù),這些函數(shù)的參數(shù)列表不同,或許是參數(shù)個(gè)數(shù)不同,或許是參數(shù)類型不同,或許是兩者都不同。重要一點(diǎn):函數(shù)重載是發(fā)生在同一個(gè)類中。調(diào)用時(shí),根據(jù)參數(shù)類型的不同進(jìn)行調(diào)用,同時(shí)編譯器在編譯期間就確定了要調(diào)用的函數(shù)。(函數(shù)的重載與多態(tài)無關(guān))。
函數(shù)覆蓋:函數(shù)覆蓋也被稱為函數(shù)重寫(override),是子類重新定義基類虛函數(shù)的方法。
構(gòu)成函數(shù)覆蓋的條件:
(1)基類的函數(shù)必須是虛函數(shù)(virtual進(jìn)行聲明)
(2)發(fā)生覆蓋的兩個(gè)函數(shù)必須分別位于派生類和基類中
(3)函數(shù)名稱和參數(shù)列表必須完全相同
由于c++,c#多態(tài)性是通過虛函數(shù)來實(shí)現(xiàn)的,所以函數(shù)覆蓋總是和多態(tài)聯(lián)系在一起,并且是程序在運(yùn)行時(shí)才確定要調(diào)用的函數(shù),因此也成為動(dòng)態(tài)綁定或者后期綁定。
?
函數(shù)隱藏:指子類中具有和基類同名的函數(shù),但是并不考慮參數(shù)列表是否相同,從而在子類中隱藏了基類的同名函數(shù)。有以下兩種情況:
(1)子類函數(shù)和基類函數(shù)完全相同,只是基類的函數(shù)沒有使用virtual關(guān)鍵字,此時(shí)基類的函數(shù)將被隱藏。
(2)子類函數(shù)和基類函數(shù)名字相同,但是參數(shù)列表不同,在這種情況下,無論基類的函數(shù)是否聲明為virtual,基類的函數(shù)都將被隱藏。
總結(jié)
以上是生活随笔為你收集整理的面向过程 VS 面向对象的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电磁兼容(EMC)标准结构的划分与分类
- 下一篇: pytest配置文件pytest.ini