自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面向?qū)ο笾?面向過程之優(yōu)

開發(fā)
面向?qū)ο笤谶^去的十多年里一直被廣泛的宣傳,現(xiàn)在已經(jīng)成為世所公認(rèn)的比面向過程更優(yōu)秀的編程模式,但是——過猶不及。本文并不是要否定OO,而是要給PO更多的肯定。這篇文字不像想象中那么長,只是些一看便知的代碼占了些篇幅,請大家花3分鐘看完,這將會是個很有意義的討論。

面向?qū)ο?/span>在過去的十多年里一直被廣泛的宣傳,現(xiàn)在已經(jīng)成為世所公認(rèn)的比面向過程更優(yōu)秀的編程模式,但是——過猶不及。Java將被作為面向?qū)ο缶幊陶Z言的典型來做說明,Python將被作為面向過程的語言來說明,雖然Python也面向?qū)ο?/span>。

1、我們需要全局變量和函數(shù)

java作為一個典型的面向?qū)ο蟮木幊陶Z言,為什么要設(shè)static關(guān)鍵字。這從側(cè)面說明,面向?qū)ο蟛皇?**的。我們需要全局性的變量、全局性的函數(shù)(方法)。

單例的設(shè)計(jì)模式,是試圖用面向?qū)ο蟮姆椒▉碜鋈中缘暮瘮?shù)。因?yàn)閷ο笾粫粍?chuàng)建一次,那該對象的方法事實(shí)上就是一個全局函數(shù)。即便單例可以用面向?qū)ο蟮姆椒▉斫鉀Q了全局函數(shù)的問題,但要獲取單例的實(shí)例,我們依然無法避免使用static變量來hold這個實(shí)例,無法避免使用static函數(shù)來獲取這個實(shí)例。

2、我們需要Callback函數(shù)

面向過程的語言會有類似這樣的代碼:

  1. Python代碼   
  2. def some_function(param...)     
  3.    //my codes...     
  4.     
  5. addListener('some_event',some_function)    
  6. def some_function(param...)  
  7.    //my codes...  
  8. addListener('some_event',some_function) 

而試圖完全對象化的Java語言有一個很尷尬的做法,Java代碼:

  1. interface MyCallback{     
  2.    MyReturenType myCallbackMethod(MyParam param,...);     
  3. }     
  4. class MyCallbackImpl implement MyCallback{     
  5.    MyReturenType myCallbackMethod(MyParam param,...){     
  6.      //My codes...     
  7.    }     
  8. }     
  9. someObj.addListener(new MyCallbackImpl());    
  10.  
  11. interface MyCallback{  
  12.    MyReturenType myCallbackMethod(MyParam param,...);  
  13. }  
  14. class MyCallbackImpl implement MyCallback{  
  15.    MyReturenType myCallbackMethod(MyParam param,...){  
  16.      //My codes...  
  17.    }  
  18. }  
  19. someObj.addListener(new MyCallbackImpl()); 

我們可以看出,為了這個回調(diào),我們定義了接口,定義了實(shí)現(xiàn)類,并且構(gòu)造了 MyCallbackImpl的對象,并且降低了代碼的可讀性。我見過許多對回調(diào)很暈的同學(xué),我想不是他們的理解能力問題,而是面向?qū)ο蟮倪@種做法本身的問題。

#p#

3、面向?qū)ο蟮拇a在重構(gòu)和重用上沒有面向過程的靈活

比如這樣的一段代碼,Java代碼:

  1. class MyClassA{     
  2.   TypeA methodA(ParamA){     
  3.     //根據(jù)ParamA,this.someField得出返回值     
  4.   }     
  5. }     
  6.     
  7. class MyClassB{     
  8.   TypeB methodB(ParamB){     
  9.      //根據(jù)ParamA,this.someField得出返回值     
  10.   }     
  11. }     
  12. ...     
  13. MyClassA objA = new MyClassA();     
  14. objA.methodA(paramA)     
  15. MyClassB objB = new MyClassB();     
  16. objB.methodB(paramB)    
  17.  
  18. class MyClassA{  
  19.   TypeA methodA(ParamA){  
  20.     //根據(jù)ParamA,this.someField得出返回值  
  21.   }  
  22. }  
  23.  
  24. class MyClassB{  
  25.   TypeB methodB(ParamB){  
  26.      //根據(jù)ParamA,this.someField得出返回值  
  27.   }  
  28. }  
  29. ...  
  30. MyClassA objA = new MyClassA();  
  31. objA.methodA(paramA)  
  32. MyClassB objB = new MyClassB();  
  33. objB.methodB(paramB) 

methodA只與paramAmethodA被限定在MyClassA的對象中調(diào)用,methodB被限定在MyClassB的對象中調(diào)用,這兩個方法由于業(yè)務(wù)范疇的原因被歸入相應(yīng)的Class。讓我們來看看這樣的代碼用面向過程的方式會如何寫,Python代碼:

  1. def methodA(paramA,paramField):     
  2.    //根據(jù)ParamA,paramField得出返回值     
  3. def methodB(paramB,paramField):     
  4.    //根據(jù)ParamB,paramField得出返回值     
  5.     
  6. class MyClassA{     
  7. }     
  8. class MyClassB{     
  9. }     
  10. ...   
  11.  
  12. objA = MyClassA()     
  13. objB = MyClassB()     
  14. methodA(paramA,objA.someField)     
  15. methodB(paramB,objB.someField)    
  16.  
  17. def methodA(paramA,paramField):  
  18.    //根據(jù)ParamA,paramField得出返回值  
  19. def methodB(paramB,paramField):  
  20.    //根據(jù)ParamB,paramField得出返回值  
  21.  
  22. class MyClassA{  
  23. }  
  24. class MyClassB{  
  25. }  
  26. ...  
  27. objA = MyClassA()  
  28. objB = MyClassB()  
  29. methodA(paramA,objA.someField)  
  30. methodB(paramB,objB.someField) 

這里的面向過程的代碼中出現(xiàn)了MyClassA和MyClassB,但這兩個類完全是空的,你可以只理解為是一個數(shù)據(jù)結(jié)構(gòu)而已?,F(xiàn)在需求發(fā)生了改變,MyClassA需要實(shí)現(xiàn)類似methodB的功能,MyClassB要實(shí)現(xiàn)類似methodA的功能。我們先看看,面向過程的代碼要做什么修改,Python代碼:

  1. def methodA(paramA,paramField):     
  2.    //根據(jù)ParamA,paramField得出返回值     
  3. def methodB(paramB,paramField):     
  4.    //根據(jù)ParamB,paramField得出返回值     
  5.     
  6. class MyClassA{     
  7. }     
  8. class MyClassB{     
  9. }     
  10. ...     
  11. objA = MyClassA()     
  12. objB = MyClassB()     
  13. methodA(paramA,objA.someField)     
  14. methodB(paramB,objB.someField)     
  15. #增加下面的兩句     
  16. methodB(paramA,objA.someField)     
  17. methodA(paramB,objB.someField)    
  18.  
  19. def methodA(paramA,paramField):  
  20.    //根據(jù)ParamA,paramField得出返回值  
  21. def methodB(paramB,paramField):  
  22.    //根據(jù)ParamB,paramField得出返回值  
  23. class MyClassA{  
  24. }  
  25. class MyClassB{  
  26. }  
  27. ...  
  28. objA = MyClassA()  
  29. objB = MyClassB()  
  30. methodA(paramA,objA.someField)  
  31. methodB(paramB,objB.someField)  
  32. #增加下面的兩句  
  33. methodB(paramA,objA.someField)  
  34. methodA(paramB,objB.someField) 

可是面向?qū)ο蟮拇a呢?等待他的將是代碼的重構(gòu),也許他可以選擇的重構(gòu)方式是static函數(shù)————本質(zhì)上是一種面向過程的方式。

#p#

引申:數(shù)據(jù)與邏輯的綁定還是分離?

面向?qū)ο缶幊淘诖a邏輯上是意味著什么?個人認(rèn)為面向?qū)ο笤诖a邏輯上意味著數(shù)據(jù)與邏輯的綁定??梢韵胂蟪?C的Structure和C的function結(jié)合成了Cpp的Class。
面向過程在代碼邏輯上意味著什么?個人認(rèn)為面向過程在代碼邏輯上意味著數(shù)據(jù)與邏輯的分離。

我們經(jīng)常說MVC,數(shù)據(jù)、邏輯、視圖分離。那么我們在最基本的代碼上就不需要這種分離了嗎?程序=數(shù)據(jù)結(jié)構(gòu)+算法,對象也可以理解為數(shù)據(jù)結(jié)構(gòu)和算法的綁定, 對象更加的接近一個程序的完整結(jié)構(gòu),而過程則更像一個代碼段。從這個角度看,很難說這是優(yōu)點(diǎn)或缺點(diǎn)。

引申:面向?qū)ο笤?jīng)輝煌但已褪色的光輝

面向?qū)ο蟪霈F(xiàn)之初,還是c語言時代,充滿了無層次結(jié)構(gòu)的函數(shù),面向?qū)ο蠼o函數(shù)帶來了歸屬地,讓函數(shù)可以被更好的整理。而如今,面向過程的語言,也可以通過包的概念來整理函數(shù)的歸屬。

此外,OO帶來訪問控制的一些概念,private,protected,public,這些訪問控制的確令人眼前一亮,但很難說他還有吸引力。對于訪問控制,在編譯原理上面向過程的語言同樣可以實(shí)現(xiàn),但更重要的還是一個好的編碼習(xí)慣,比如python的__前綴函數(shù),開發(fā)者會自然的規(guī)避調(diào)用它。

引申:面向?qū)ο笞钣绪攘Φ牡胤皆谀模?

個人認(rèn)為,面向?qū)ο?**的吸引力在于他的表現(xiàn)力。看這樣一段代碼,Java代碼:

  1. class Fish{     
  2.   void swim(){     
  3.    //the fish swimming     
  4.  }     
  5. }     
  6.     
  7. Fish fish=new Fish()     
  8. fish.swim()    
  9. class Fish{  
  10.   void swim(){  
  11.    //the fish swimming  
  12.  }  
  13. }  
  14. Fish fish=new Fish()  
  15. fish.swim() 

來看面向過程的實(shí)現(xiàn),Python代碼:

  1. def swim(fish):     
  2.   //the fish swimming     
  3. fish = Fish()     
  4. swim(fish)    
  5. def swim(fish):  
  6.   //the fish swimming  
  7. fish = Fish()  
  8. swim(fish) 

面向?qū)ο蟮拇a,我們很直觀的看到 fish.swim() 是魚游泳。而面向過程的代碼則是 swim(fish),游泳這條魚,函數(shù)定義也許改做 make_fish_swim(fish) 更合適。

尾聲:什么時候用OO,什么時候用PO?

浮在海上的冰山,大部分的內(nèi)容在海面以下。海面以上的用OO來表現(xiàn)會更美,海面以下的用PO來表現(xiàn)會更合適。

【編輯推薦】

  1. Python繼承體現(xiàn)面向?qū)ο筇卣?/span>
  2. PHP+Java的開發(fā)經(jīng)驗(yàn):不要太面向?qū)ο?/span>
  3. 面向?qū)ο笤O(shè)計(jì)原則之單一職責(zé) 

 

責(zé)任編輯:王曉東 來源: javaeye
相關(guān)推薦

2022-07-30 23:41:53

面向過程面向?qū)ο?/a>面向協(xié)議編程

2023-11-30 08:00:54

面向?qū)ο?/a>面向切面

2023-04-26 00:15:32

python面向?qū)ο?/a>java

2023-01-10 09:38:09

面向對象系統(tǒng)

2019-06-13 11:50:41

Python面向?qū)ο?/a>編程語言

2013-03-11 09:23:22

Go語言面向?qū)ο?/a>

2011-07-05 14:42:46

java

2023-03-10 07:43:50

UML圖OOA面向?qū)ο?/a>

2010-07-08 13:35:39

UML面向?qū)ο?/a>

2010-12-23 13:35:05

面向過程

2009-10-21 18:09:12

VB入門教程

2009-09-27 14:12:12

面向?qū)ο笤O(shè)計(jì)單一職責(zé)

2013-08-21 17:20:49

.NET面向?qū)ο?/a>

2013-04-17 10:46:54

面向?qū)ο?/a>

2017-04-21 09:07:39

JavaScript對象編程

2012-01-17 09:34:52

JavaScript

2015-10-16 13:41:52

程序對象設(shè)計(jì)

2013-03-14 11:17:46

2012-12-13 11:01:42

IBMdW

2021-10-21 18:47:37

JavaScript面向對象
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號