7大原則
- 單一職責原則(Single Responsibility Principle SRP)
如何劃分一個類、一個函式的職責,每個人都有自己的看法,這需要根據個人經驗、 具體的業務邏輯而定。但是,它也有一些基本的指導原則,例如,兩個完全不一樣的功能就不應該放在一個類中。一個類中應該是一組相關性很高的函式、資料的封裝。工程師可以不斷地審視自己的程式碼,根據具體的業務、功能對類進行相應的拆分,這是程式設計師優化程式碼邁出的第一步。 - 開閉原則(Open Closed Principle OCP)
軟體中的物件(類、模組、函式等)應該對於擴充套件是開放的,但是,對於修改是封閉的。 - 里氏替換原則(Liskov Substitution Principle LSP)
所有引用基類的地方必須能透明地使用其子類的物件。通俗點講,只要父類能出現的地方子類就可以出現,而且替換為子類也不會產生任何錯誤或異常,使用者可能根本就不需要知道是父類還是子類。
里氏替換原則的關鍵就是建立抽象,通過抽象建立規範,具體的實現在執行時替換掉抽象,保證系統的擴充套件性、靈活性。開閉原則和里氏替換原則往往是生死相依、不棄不離的,通過里氏替換來達到對擴充套件開放,對修改關閉的效果。然而,這兩個原則都同時強調了一個OOP的重要特性抽象,因此,在開發過程中運用抽象是走向程式碼優化的重要一步。
比如ViewGroup中的addView(View view),這個view可以是View的各種子類,也可以是自定義View。 - 依賴倒置原則(Dependence Inversion Principle DIP)
模組間的依賴通過抽象發生,實現類之間不發生直接的依賴關係,其依賴關係是通過介面或抽象類產生的。 - 介面隔離原則(Interface Segregation Principle ISP)
客戶端不應該依賴它不需要的介面。另一種定義是:類間的依賴關係應該建立在最小的介面上。 - 迪米特原則(Law of Demeter LOD),又叫最少知識原則(Least Knowledge Principle LKP)
一個物件應該對其他物件有最少的瞭解。通俗地講,一個類應該對自己需要耦合或呼叫的類知道得最少,類的內部如何實現與呼叫者或者依賴者沒關係,呼叫者或者依賴者只需要知道它需要的方法即可,其他的可一概不用管。類與類之間的關係越密切,耦合度越大,當一個類發生改變時,對另一個類的影響也越大。 - 組合/聚合複用原則(Composition/Aggregation Principle CARP)
在物件導向的設計中,如果直接繼承基類,會破壞封裝,因為繼承將基類的實現細節暴露給子類;如果基類的實現發生改變,則子類的實現也不得不發生改變;從基類繼承而來的實現是靜態的,不可能在執行時發生改變,沒有足夠的靈活性。於是就提出了組合/聚合複用原則,也就是在實際開發設計中,儘量使用合成/聚合,不要使用類繼承。即在一個新的物件裡面使用一些已有的物件,使之成為新物件的一部分,新物件通過向這些物件的委派達到複用已有功能的目的。就是說要儘量的使用合成和聚合,而不是繼承關係達到複用的目的。
23中設計模式
- 單例模式
①靜態常量(靜態常量或者靜態程式碼塊)
②雙重檢查同步程式碼塊
③靜態內部類
④列舉
⑤AtomicRerence - Builder模式
通常作為配置類的構建器將配置的構建和表示分離開來,同時也是將配置從目標類中隔離出來, 避免過多的setter方法。Builder模式比較常見的實現形式是通過呼叫鏈實現, 這樣使得程式碼更簡介、 易懂。
public class Config {
int config1;
int config2;
private Config () {
}
public static class Buider {
int config1;
int config2;
public Buider setConfig1(int config1){
this.config1 = config1;
return this;
}
public Buider setConfig2(int config2){
this.config2 = config2;
return this;
}
private void apply(Config config){
config.config1 = this.config1;
config.config2 = this.config2;
}
public Config create(){
Config config = new config();
this.apply(config);
return config;
}
}
複製程式碼
-
原型模式
原型模式本質上就是物件拷貝,容易出現的問題是深拷貝、淺拷貝。使用原型模式可以解決構建複雜物件的資源消耗問題,能夠在某些場景下提升建立物件的效率。 還有一 個重要的用途就是保護性拷貝,也就是某個物件對外可能是隻讀的,為了防止外部對這個只讀物件修改, 通常可以通過返回一個物件拷貝的形式實現只讀的限制。 -
工廠方法模式
-
抽象工廠模式
在任何需要生成複雜物件的地方,都可以使用工廠方法模式。複雜物件適合使用工廠模式,用 new就可以完成建立的物件無需使用工廠模式。方便建立同種產品型別的複雜引數物件。 -
策略模式
如果將這些演算法或者策略抽象出來,提供一個統一的介面,不同的演算法或者策略有不同的實現 類,這樣在程式客戶端就可以通過注入不同的實現物件來實現演算法或者策略的動態替換,這種模式 的可擴充套件性、可維護性也就更高。策略模式主要用來分離演算法,在相同的行為抽象下有不同的具體實現策略。這個模式很好地演示了開閉原則,也就是定義抽象,注入不同的實現,從而達到很好的可擴充套件性。 -
狀態模式
狀態模式中的行為是由狀態來決定的,不同的狀態下有不同的行為。狀態模式和策略模式的結 構幾乎完全一樣,但它們的目的、本質卻完全不一樣。狀態模式的行為是平行的、不可替換的, 策略模式的行為是彼此獨立、可相互替換的。用一句話來表述,狀態模式把物件的行為包裝在不同的狀態物件裡,每一個狀態物件都有一個共同的抽象狀態基類。狀態模式的意圖是讓一個物件在其內部狀態改變的時候,其行為也隨之改變。 -
責任鏈模式
使多個物件都有機會處理請求,從而避免了請求的傳送者和接收者之間的耦合關係。將這些物件連成一條鏈,並沿著這條鏈傳遞該請求,直到有物件處理它為止。 -
直譯器模式
給定一個語言,定義它的文法的一種表示,並定義一個直譯器,該直譯器使用該表示來解釋語言中的句子。 -
命令列模式
將呼叫者與行為實現者解耦 -
觀察者模式
定義物件間一種一對多的依賴關係,使得每當一個物件改變狀態,則所有依賴千它的物件都會得到通知並被自動更新。 -
備忘錄模式
在不破壞封閉的前提下,捕獲一個物件的內部狀態,並在該物件之外儲存這個狀態,這樣,以後就可以將該物件恢復到原先儲存的狀態。 -
迭代器模式
提供一種方法順序訪問一個容器物件中的各個元素,而又不需要暴露該物件的內部表示。 -
模板方法模式
定義一個操作中的演算法的框架,而將一些步驟延遲到子類中,使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。 使用場景:
(1)多個子類有公有的方法, 並且邏輯基本相同時。
(2)重要、複雜的演算法,可以把核心演算法設計為模板方法週一邊的相關細節功能則由各個子類實現。
(3)重構時,模板方法模式是一個經常使用的模式,把相同的程式碼抽取到父類中,然後通過鉤 子函式約束其行為。 -
訪問者模式
定義及使用場景
定義:
封裝一些作用於某種資料結構中的各元素的操作,它可以在不改變這個資料結構的前提下定義作用於這些元素的新的操作。
可以對定義這麼理解:有這麼一個操作,它是作用於一些元素之上的,而這些元素屬於某一個物件結構。同時這個操作是在不改變各元素類的前提下,在這個前提下定義新操作是訪問者模式精髓中的精髓。
使用場景:
(1)物件結構比較穩定,但經常需要在此物件結構上定義新的操作。
(2)需要對一個物件結構中的物件進行很多不同的且不相關的操作,而需要避免這些操作“汙染”這些物件的類,也不希望在增加新操作時修改這些類。 -
中介者模式
定義:中介者模式包裝了一系列物件相互作用的方式,使得這些物件不必相互明顯作用。從而使它們可以鬆散耦合。當某些物件之間的作用發生改變時,不會立即影響其他的一些物件之間的作用。保證這些作用可以彼此獨立的變化。
使用場景: 當物件之間的互動操作很多且每個物件的行為操作都依賴彼此時,為防止在修改一個物件的行為時,同時涉及很多其他物件的行為,可使用中介者模式。
- 代理模式
靜態代理,動態代理。 - 組合模式
View和ViewGroup,Folder和File - 介面卡模式
類介面卡、物件介面卡。Recyclerview的adapter是將資料轉成items。 - 裝飾者模式
動態地給一個物件新增一些額外的職責。 與代理模式的區別:
- 裝飾模式,突出的是執行期增加行為,這和繼承是不同的,繼承是在編譯期增加行為。
- 代理模式,控制物件的訪問。
- 享元模式
比如連線池、執行緒池等各種快取池,複用減少記憶體、建立開銷和gc。 - 外觀模式
向外提供SDK時的封裝。子模組的封裝。向外提供一個統一高層次的介面,遮蔽實現細節。 - 橋接模式
將抽象部分與實現部分分離,使它們都可以獨立地進行變化。橋接模式將繼承關係轉化成關聯關係,它降低了類與類之間的耦合度,減少了系統中類的數量,也減少了程式碼量。