面向對象思想精華總結

  • 一、三大特性
    • 封裝
    • 繼承
    • 多態
  • 二、類圖
    • 泛化關系 (Generalization)
    • 實現關系 (Realization)
    • 聚合關系 (Aggregation)
    • 組合關系 (Composition)
    • 關聯關系 (Association)
    • 依賴關系 (Dependency)
  • 三、設計原則
    • S.O.L.I.D
    • 其他常見原則
  • 參考資料

一、三大特性

封裝

利用抽象數據類型將數據和基于數據的操作封裝在一起,使其構成一個不可分割的獨立實體。數據被保護在抽象數據類型的內部,盡可能地隱藏內部的細節,只保留一些對外的接口使其與外部發生聯系。用戶無需關心對象內部的細節,但可以通過對象對外提供的接口來訪問該對象。

優點:

  • 減少耦合:可以獨立地開發、測試、優化、使用、理解和修改
  • 減輕維護的負擔:可以更容易被理解,并且在調試的時候可以不影響其他模塊
  • 有效地調節性能:可以通過剖析來確定哪些模塊影響了系統的性能
  • 提高軟件的可重用性
  • 降低了構建大型系統的風險:即使整個系統不可用,但是這些獨立的模塊卻有可能是可用的

以下 Person 類封裝 name、gender、age 等屬性,外界只能通過 get() 方法獲取一個 Person 對象的 name 屬性和 gender 屬性,而無法獲取 age 屬性,但是 age 屬性可以供 work() 方法使用。

注意到 gender 屬性使用 int 數據類型進行存儲,封裝使得用戶注意不到這種實現細節。并且在需要修改 gender 屬性使用的數據類型時,也可以在不影響客戶端代碼的情況下進行。

public class Person {private String name;private int gender;private int age;public String getName() {return name;}public String getGender() {return gender == 0 ? "man" : "woman";}public void work() {if (18 <= age && age <= 50) {System.out.println(name + " is working very hard!");} else {System.out.println(name + " can't work any more!");}}
}

繼承

繼承實現了 IS-A 關系,例如 Cat 和 Animal 就是一種 IS-A 關系,因此 Cat 可以繼承自 Animal,從而獲得 Animal 非 private 的屬性和方法。

繼承應該遵循里氏替換原則,子類對象必須能夠替換掉所有父類對象。

Cat 可以當做 Animal 來使用,也就是說可以使用 Animal 引用 Cat 對象。父類引用指向子類對象稱為 向上轉型

Animal animal = new Cat();

多態

多態分為編譯時多態和運行時多態:

  • 編譯時多態主要指方法的重載
  • 運行時多態指程序中定義的對象引用所指向的具體類型在運行期間才確定

運行時多態有三個條件:

  • 繼承
  • 覆蓋(重寫)
  • 向上轉型

下面的代碼中,樂器類(Instrument)有兩個子類:Wind 和 Percussion,它們都覆蓋了父類的 play() 方法,并且在 main() 方法中使用父類 Instrument 來引用 Wind 和 Percussion 對象。在 Instrument 引用調用 play() 方法時,會執行實際引用對象所在類的 play() 方法,而不是 Instrument 類的方法。

public class Instrument {public void play() {System.out.println("Instument is playing...");}
}
public class Wind extends Instrument {public void play() {System.out.println("Wind is playing...");}
}
public class Percussion extends Instrument {public void play() {System.out.println("Percussion is playing...");}
}
public class Music {public static void main(String[] args) {List<Instrument> instruments = new ArrayList<>();instruments.add(new Wind());instruments.add(new Percussion());for(Instrument instrument : instruments) {instrument.play();}}
}
Wind is playing...
Percussion is playing...

二、類圖

以下類圖使用 PlantUML 繪制,更多語法及使用請參考:http://plantuml.com/ 。

泛化關系 (Generalization)

用來描述繼承關系,在 Java 中使用 extends 關鍵字。


@startumltitle Generalizationclass Vihical
class Car
class TrunckVihical <|-- Car
Vihical <|-- Trunck@enduml

實現關系 (Realization)

用來實現一個接口,在 Java 中使用 implements 關鍵字。


@startumltitle Realizationinterface MoveBehavior
class Fly
class RunMoveBehavior <|.. Fly
MoveBehavior <|.. Run@enduml

聚合關系 (Aggregation)

表示整體由部分組成,但是整體和部分不是強依賴的,整體不存在了部分還是會存在。


@startumltitle Aggregationclass Computer
class Keyboard
class Mouse
class ScreenComputer o-- Keyboard
Computer o-- Mouse
Computer o-- Screen@enduml

組合關系 (Composition)

和聚合不同,組合中整體和部分是強依賴的,整體不存在了部分也不存在了。比如公司和部門,公司沒了部門就不存在了。但是公司和員工就屬于聚合關系了,因為公司沒了員工還在。


@startumltitle Compositionclass Company
class DepartmentA
class DepartmentBCompany *-- DepartmentA
Company *-- DepartmentB@enduml

關聯關系 (Association)

表示不同類對象之間有關聯,這是一種靜態關系,與運行過程的狀態無關,在最開始就可以確定。因此也可以用 1 對 1、多對 1、多對多這種關聯關系來表示。比如學生和學校就是一種關聯關系,一個學校可以有很多學生,但是一個學生只屬于一個學校,因此這是一種多對一的關系,在運行開始之前就可以確定。


@startumltitle Associationclass School
class StudentSchool "1" - "n" Student@enduml

依賴關系 (Dependency)

和關聯關系不同的是,依賴關系是在運行過程中起作用的。A 類和 B 類是依賴關系主要有三種形式:

  • A 類是 B 類方法的局部變量;
  • A 類是 B 類方法的參數;
  • A 類向 B 類發送消息,從而影響 B 類發生變化。

@startumltitle Dependencyclass Vihicle {move(MoveBehavior)
}interface MoveBehavior {move()
}note "MoveBehavior.move()" as NVihicle ..> MoveBehaviorVihicle .. N@enduml

三、設計原則

S.O.L.I.D

簡寫全拼中文翻譯
SRPThe Single Responsibility Principle單一責任原則
OCPThe Open Closed Principle開放封閉原則
LSPThe Liskov Substitution Principle里氏替換原則
ISPThe Interface Segregation Principle接口分離原則
DIPThe Dependency Inversion Principle依賴倒置原則

1. 單一責任原則

修改一個類的原因應該只有一個。

換句話說就是讓一個類只負責一件事,當這個類需要做過多事情的時候,就需要分解這個類。

如果一個類承擔的職責過多,就等于把這些職責耦合在了一起,一個職責的變化可能會削弱這個類完成其它職責的能力。

2. 開放封閉原則

類應該對擴展開放,對修改關閉。

擴展就是添加新功能的意思,因此該原則要求在添加新功能時不需要修改代碼。

符合開閉原則最典型的設計模式是裝飾者模式,它可以動態地將責任附加到對象上,而不用去修改類的代碼。

3. 里氏替換原則

子類對象必須能夠替換掉所有父類對象。

繼承是一種 IS-A 關系,子類需要能夠當成父類來使用,并且需要比父類更特殊。

如果不滿足這個原則,那么各個子類的行為上就會有很大差異,增加繼承體系的復雜度。

4. 接口分離原則

不應該強迫客戶依賴于它們不用的方法。

因此使用多個專門的接口比使用單一的總接口要好。

5. 依賴倒置原則

高層模塊不應該依賴于低層模塊,二者都應該依賴于抽象;抽象不應該依賴于細節,細節應該依賴于抽象。

高層模塊包含一個應用程序中重要的策略選擇和業務模塊,如果高層模塊依賴于低層模塊,那么低層模塊的改動就會直接影響到高層模塊,從而迫使高層模塊也需要改動。

依賴于抽象意味著:

  • 任何變量都不應該持有一個指向具體類的指針或者引用;
  • 任何類都不應該從具體類派生;
  • 任何方法都不應該覆寫它的任何基類中的已經實現的方法。

其他常見原則

除了上述的經典原則,在實際開發中還有下面這些常見的設計原則。

簡寫全拼中文翻譯
LODThe Law of Demeter迪米特法則
CRPThe Composite Reuse Principle合成復用原則
CCPThe Common Closure Principle共同封閉原則
SAPThe Stable Abstractions Principle穩定抽象原則
SDPThe Stable Dependencies Principle穩定依賴原則

1. 迪米特法則

迪米特法則又叫作最少知識原則(Least Knowledge Principle,簡寫 LKP),就是說一個對象應當對其他對象有盡可能少的了解,不和陌生人說話。

2. 合成復用原則

盡量使用對象組合,而不是通過繼承來達到復用的目的。

3. 共同封閉原則

一起修改的類,應該組合在一起(同一個包里)。如果必須修改應用程序里的代碼,我們希望所有的修改都發生在一個包里(修改關閉),而不是遍布在很多包里。

4. 穩定抽象原則

最穩定的包應該是最抽象的包,不穩定的包應該是具體的包,即包的抽象程度跟它的穩定性成正比。

5. 穩定依賴原則

包之間的依賴關系都應該是穩定方向依賴的,包要依賴的包要比自己更具有穩定性。

參考資料

  • Java 編程思想
  • 敏捷軟件開發:原則、模式與實踐
  • 面向對象設計的 SOLID 原則
  • 看懂 UML 類圖和時序圖
  • UML 系列——時序圖(順序圖)sequence diagram
  • 面向對象編程三大特性 ------ 封裝、繼承、多態

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/444108.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/444108.shtml
英文地址,請注明出處:http://en.pswp.cn/news/444108.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數組名與指向數組的指針之間的聯系與區別【數據結構】

我們遇到一個非常棘手的問題&#xff0c;這個問題就是&#xff0c;對于一堆數據來說&#xff0c;我們進行存儲&#xff0c;放到一個指定的倉庫當中&#xff0c;先前我們使用數組加加標的形式進行訪問倉庫當中的元素位置&#xff0c;但是呢&#xff0c;現在我們使用的是一個指針…

Struts2的action中處理JSONP方式提交的中文亂碼問題:

昨天在做公司網站的時候出現了一個中文亂碼問題&#xff0c;讓我郁悶了一晚上和一上午&#xff0c;最后在網友的提示下&#xff0c;我終于解決了&#xff0c;現在寫出來供后來的兄弟們參考&#xff1a; 1.問題是這樣的&#xff0c;就是客戶端是以JSONP的方式提交的數據&#x…

leetcode509. 斐波那契數(矩陣快速冪)

斐波那契數&#xff0c;通常用 F(n) 表示&#xff0c;形成的序列稱為斐波那契數列。該數列由 0 和 1 開始&#xff0c;后面的每一項數字都是前面兩項數字的和。也就是&#xff1a; F(0) 0, F(1) 1 F(N) F(N - 1) F(N - 2), 其中 N > 1. 給定 N&#xff0c;計算 F(N)。…

insert函數的修改,

我們來看一下圖片當中的第2個圓圈&#xff0c;為什么使用size來相加呢&#xff1f;我們知道一開始我們定義的初始空間為init_size;我們想一下啊&#xff0c;如果是第1次進行空間的增加&#xff0c;那么我們使用InIt來進行相加是可以的&#xff0c;但是當第2次想加我們再想開辟空…

leetcode520. py解字符串真是太殘暴了

給定一個單詞&#xff0c;你需要判斷單詞的大寫使用是否正確。 我們定義&#xff0c;在以下情況時&#xff0c;單詞的大寫用法是正確的&#xff1a; 全部字母都是大寫&#xff0c;比如"USA"。 單詞中所有字母都不是大寫&#xff0c;比如"leetcode"。 如果…

【數據結構】線性表大咖

循環鏈表的介紹 概念&#xff1a;鏈表的最后一個節點的指針&#xff0c;由原來的 空指針變成指向第1個節點的鏈表。 類比&#xff1a;我們進行串珠子的操作&#xff0c;將首尾通過線進行連接&#xff0c;同樣我們的鏈表就是通過指針指向的方式進行連接&#xff0c;使其成為一…

leetcode551. 學生出勤記錄 I

給定一個字符串來代表一個學生的出勤記錄&#xff0c;這個記錄僅包含以下三個字符&#xff1a; A : Absent&#xff0c;缺勤 L : Late&#xff0c;遲到 P : Present&#xff0c;到場 如果一個學生的出勤記錄中不超過一個A(缺勤)并且不超過兩個連續的L(遲到),那么這個學生會被獎…

一元多項式的表示和相加【數據結構】

一元多項式的表示和相加 運算只是一個定義&#xff0c;一切的一切&#xff0c;到最后都必須歸咎于存儲結構當中&#xff0c;實現物理存儲&#xff0c;一元多項式包括數據對象數據關系以及數據之間的各種操作&#xff0c; 一元多項式的實現&#xff1a;用帶表頭結點的有序鏈表…

線性結構基本概念【數據結構】F

線性表的概念&#xff1a;線性表是一種最簡單的線性結構&#xff0c;線性結構是單個數據元素的有序結合 線性結構的基本特征為&#xff1a; 第一&#xff0c;集合中必存在唯一的一個第1元素&#xff0c; 第二&#xff0c;集合中必存在唯一的一個最后元素&#xff0c; 第三&am…

leetcode589. N叉樹的前序遍歷

給定一個 N 叉樹&#xff0c;返回其節點值的前序遍歷。 例如&#xff0c;給定一個 3叉樹 : 返回其前序遍歷: [1,3,5,6,2,4]。 思路&#xff1a;先放入自己&#xff0c;再依次遍歷孩子。 /* // Definition for a Node. class Node {public int val;public List<Node> c…

ORA-00001 違反唯一約束條件

程序跑出下面的異常&#xff1a;com.ibm.websphere.ce.cm.DuplicateKeyException: ORA-00001: 違反唯一約束條件 (EOMS3.SYS_C0024492)&#xff0c;參考下面的文章了解到我的程序可能是序列的問題。&#xff08;果然是序列產生的最小值設置的太小&#xff0c;將序列值設置大之后…

順序結構實現【數據結構】

雖然在數據結構當中是先出現的線性表&#xff0c;然后出現的是數組 一&#xff1a;線性表的順序存儲結構 順序映象&#xff1a;用一組地址連續的存儲單元依次存放線性表當中的數據元素 線性表的起始地址&#xff1a;線性存儲第一個數據元素的地址&#xff0c;我們也稱作是基地址…

leetcode590. N叉樹的后序遍歷

給定一個 N 叉樹&#xff0c;返回其節點值的后序遍歷。 例如&#xff0c;給定一個 3叉樹 : 思路&#xff1a;先遍歷所有孩子&#xff0c;再放入自己。 /* // Definition for a Node. class Node {public int val;public List<Node> children;public Node() {}public No…

鏈表的形式【F】

數據元素之間的關系在計算機中有兩種表示方法: 順序映象, 非順序映象. 對應兩種存儲結構: 順序存儲結構, 鏈式存儲結構 線性結構就是一種邏輯關系&#xff0c;方便我們對數據進行研究但是不考慮真實的存儲結構 數據是什么&#xff1f; 數據是能夠反應一定內容的一組數據類型的…

leetcode892. 三維形體的表面積

在 N * N 的網格上&#xff0c;我們放置一些 1 * 1 * 1 的立方體。 每個值 v grid[i][j] 表示 v 個正方體疊放在對應單元格 (i, j) 上。 請你返回最終形體的表面積。 示例 1&#xff1a; 輸入&#xff1a;[[2]] 輸出&#xff1a;10 示例 2&#xff1a; 輸入&#xff1a;…

leetcode914. 卡牌分組

給定一副牌&#xff0c;每張牌上都寫著一個整數。 此時&#xff0c;你需要選定一個數字 X&#xff0c;使我們可以將整副牌按下述規則分成 1 組或更多組&#xff1a; 每組都有 X 張牌。 組內所有的牌上都寫著相同的整數。 僅當你可選的 X > 2 時返回 true。 示例 1&#xf…

單鏈表的實現【數據結構】

思考&#xff1a; 1.是否能夠將原來指針的方向改為向前指向呢&#xff1f; 2.是否能夠有兩個指針域的操作呢&#xff1f; 了解&#xff1a; 單鏈表是應用最廣泛的一種形式&#xff0c;還有雙向鏈表以及循環鏈表&#xff0c;這些都是要進行討論的 結構體定義的是什么&#xff1f…

(詳細圖解)VS2017安裝教程

VS 2017 版本同 15 版一樣&#xff0c;細分為三個版本&#xff0c;分別是&#xff1a; 社區版&#xff08;Community&#xff09;&#xff1a;免費提供給單個開發人員&#xff0c;給予初學者及大部分程序員支持&#xff0c;可以無任何經濟負擔、合法地使用。企業版&#xff1a…

鏈表的代碼實現【數據結構F】

單鏈表的特點&#xff1a;每次結點的分配都是動態進行分配的&#xff0c;melloc函數實現的功能是開辟一塊新的內存空間&#xff0c;但是返回的是一個地址&#xff0c;只能是地址&#xff0c;沒有別名的事情&#xff0c;那就有點難辦了&#xff0c;這是一種間接的尋址&#xff0…

(圖文詳細)如何使用Code::Blocks運行c/cpp文件?

1) 新建源文件 打開 CodeBlocks &#xff0c;在上方菜單欄中選擇 “文件 --> 新建 --> 空白文件”&#xff0c;如下圖所示&#xff1a; 或者直接按下 Ctrl Shift N 組合鍵&#xff0c;都會新建一個空白的源文件&#xff0c;如下圖所示&#xff1a; 在空白源文件中輸入…