天天看點

opp ,oop ,aop

概念

面向過程程式設計OPP:Procedure Oriented Programming,是一種以事物為中心的程式設計思想。主要關注“怎麼做”,即完成任務的具體細節 , 是一系列程式指令的集合。

面向對象程式設計OOP:Object Oriented Programming,是一種以對象為基礎的程式設計思想。主要關注“誰來做”,即完成任務的對象,基本單元是對象(資料和操作資料的方法)。

面向切面程式設計AOP:Aspect Oriented Programming,基于OOP延伸出來的程式設計思想。主要實作的目的是針對業務處理過程中的切面進行提取,它所面對的是處理過程中的某個步驟或階段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。

比如完成“吃飯”這個任務。

面向過程的寫法,需要封裝一個eat()函數:

如果是狗吃屎,則eat(狗,屎);

如果是人吃肉,則eat(人,肉);

eat是人和狗共用的吃飯本能。

那如果之後要處理貓吃魚、魚吃蝦、奧特曼吃小怪獸呢?eat函數中就會存在大量的if…else的判斷,這段代碼,無疑是很惡心的。

如果是面向對象思想,如何來解決這個問題呢?

我們發現,狗、人、貓、魚、奧特曼,都有一個“吃”的共性。我們抽象出每個受體的類,然後繼承,這樣都具有“吃”的方法。

當我們想要執行狗吃屎時,那就“狗->eat(屎)”,這樣,我們從面向過程維護eat()的焦點,轉移到了面向對象維護角色的焦點上來。我們隻需要維護好不同的角色(類)就好了,并且狗的eat不會影響到貓的eat,貓的eat也不會影響到人的eat。

是以,oop思想非常貼近軟體工程高内聚的思想:自己管好自己的東西,自己做好自己的事情。

OPP和OOP

面向過程是最為實際的一種思考方式,就算是面向對象的方法也是含有面向過程的思想。可以說面向過程是一種基礎的方法。它考慮的是實際地實作。一般的面向過程是從上往下步步求精,是以面向過程最重要的是子產品化的思想方法。當程式規模不是很大時,面向過程的方法還會展現出一種優勢。因為程式的流程很清楚,按着子產品與函數的方法可以很好的組織。

面向對象是基于對象概念,以對象為中心,以類和繼承為構造機制,來認識、了解、刻畫客觀世界和設計、建構相應的軟體系統。類和繼承是是适應人們一般思維方式的描述範式。方法是允許作用于該類對象上的各種操作。這種對象、類、消息和方法的程式設計範式的基本點在于對象的封裝性和類的繼承性。通過封裝能将對象的定義和對象的實作分開,通過繼承能展現類與類之間的關系,以及由此帶來的動态聯編和實體的多态性。

AOP

面向切面程式設計主要實作的目的是針對業務處理過程中的切面進行提取,它所面對的是處理過程中的某個步驟或階段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。

那麼,AOP如何展現?

這裡可以聯想一下laravel的中間件、javaweb的攔截器、vue的Decorator…它們都是AOP思想的實踐。裝飾器模式、代理模式,它們也是基于AOP思想的設計模式。

AOP思想,指導我們通過找到平整切面的形式,插入新的代碼,使新插入的代碼對切面上下原有流程的傷害降到最低。

舉個栗子:

我們拿laravel中間件做什麼?

權限、日志、請求過濾、請求頻率限制、csrf過濾……

我們知道,中間件對于controller的業務邏輯,不會有任何傷害。

如果沒有這個切面,我們想要記錄請求日志,可能需要在每個controller的具體方法中寫日志記錄的代碼,或者調用日志記錄的函數、方法。

這會使一段記錄日志的代碼,或調用記錄日志的調用語句出現在許多controller中,這與controller原本要關注的邏輯無關,使controller職責不單一,提高維護成本。

當然,我們可能會寫一個父類,讓許多controller來繼承這個父類,然後統一在父類的__construct方法中記錄日志,以此來解決耦合問題。

但實際上,這個父類的construct方法,不正是一個切面嗎?它在原有流程中截取了一個切面,在切面中植入代碼,以達到承上啟下的作用,并且不對上下文産生傷害。

從這個例子中,我們也能得出另外一個思考:AOP指導我們尋找切面,但找到合适的切面,也尤為重要。就像上文,父類構造函數的切面和中間件的切面比起來,顯然中間件這個切面更利于維護,你可以靈活選擇中間件,但你無法靈活選擇父類,因為決定你的controller繼承什麼父類的,不是切面中的代碼,而是controller本身處理什麼邏輯。

許多項目,OPP、OOP、AOP是同時存在的,它們是程式設計範式,是一種指導程式設計的思想,并非不能互相配合。