里氏替換原則
里氏替換原則的英文全稱是Liskov Substitution Principle在刺,縮寫是LSP义屏。
LSP第一種定義是:如果對(duì)每一個(gè)類型的為S的對(duì)象O1闻坚,都有類型為T的對(duì)象O2,使得以T定義的所有程序P在所有對(duì)象O1都替換成O2時(shí)路操,程序P的行為不會(huì)發(fā)生變化徘禁,那么類型S是類型T的子類型诅诱。這不太好理解。
LSP的第二種定義是:所有引用基類的地方必須能透明地使用其子類的對(duì)象送朱。通俗的講就是:只要父類能出現(xiàn)的地方子類就可以出現(xiàn)娘荡,而且替換為子類也不會(huì)產(chǎn)生任何錯(cuò)誤或者異常,使用者可能根本就不需要知道是父類還是子類骤菠,但是,反過(guò)來(lái)就不行了疤孕,有子類出現(xiàn)的地方商乎,父類未必就能適應(yīng)。因?yàn)樽宇愑械臇|西父類不一定有祭阀。
說(shuō)了這么多鹉戚,最終總結(jié)就兩個(gè)字:抽象。為了便于理解這個(gè)原則专控,我們寫了一個(gè)簡(jiǎn)單示例來(lái)描述抹凳,先看UML圖:
再來(lái)看看具體的代碼:
/**
* 窗口類
*/
public class Window {
public show(View chile) {
chile.draw();
}
}
/**
* 建立視圖抽象,測(cè)量視圖的寬高為公用代碼伦腐,繪制實(shí)現(xiàn)交給具體的子類
*/
public abstract class View {
public abstract void draw();
public void measure(int width,int height) {
}
}
/**
* Button的具體實(shí)現(xiàn)
*/
public class Button extends View {
@Override
public void draw() {
//繪制Button
}
}
/**
* TextView的具體實(shí)現(xiàn)
*/
public class TextView extends View {
@Override
public void draw() {
//繪制TextV
}
}
上述示例中赢底,Window依賴于View,而View定義了一個(gè)視圖抽象,measure是各個(gè)子類共享的方法幸冻,子類通過(guò)覆寫View的draw方法實(shí)現(xiàn)各自的功能粹庞。任何繼承自View的子類都可以設(shè)置給Window的show方法,這就是里氏替換原則洽损。通過(guò)里氏替換庞溜,就可以自定義各自各樣的view,然后傳遞個(gè)Window碑定,Window負(fù)責(zé)組織view流码,并且將View顯示到屏幕上。
里氏替換原則的核心是抽象延刘,抽象又依賴于繼承這個(gè)特性漫试,在OOP當(dāng)中,繼承的優(yōu)缺點(diǎn)都相當(dāng)?shù)拿黠@访娶。優(yōu)點(diǎn)為:
- 代碼重用商虐,減少創(chuàng)建的成本,每個(gè)子類擁有父類的方法和屬性
- 子類和父類基本相似崖疤,但又與父類有所區(qū)別
- 提高代碼的可擴(kuò)展性,實(shí)現(xiàn)父類的方法就可以了秘车,很多開源框架的擴(kuò)展接口都是通過(guò)繼承父類完成的。
- 提高產(chǎn)品或項(xiàng)目的開放性劫哼。
繼承的缺點(diǎn):
- 繼承是侵入性的叮趴,只要繼承就必須擁有父類的所有屬性和方法
- 可能造成子類代碼冗余、靈活性降低权烧,因?yàn)樽宇惐仨殦碛懈割惖膶傩院头椒?/li>
- 增強(qiáng)了耦合性眯亦。當(dāng)父類的常量、變量和方法被修改時(shí)般码,必須考慮子類的修改妻率,而且在缺乏規(guī)范的環(huán)境下,這種修好可能帶來(lái)非常糟糕的結(jié)果---大片的代碼需要重構(gòu)板祝。
結(jié)束
開閉原則中的示例圖片緩存系統(tǒng)也很好地反應(yīng)了里氏替換原則宫静,即MemoryCache、DiskCache券时、DoubleCache都可以替換成ImageCache的工作孤里,并保證行為的正確性。實(shí)際中橘洞,開閉原則和里氏替換原則往往是相互關(guān)聯(lián)的捌袜,通過(guò)里氏替換來(lái)達(dá)到擴(kuò)展開放、修改關(guān)閉的效果炸枣。然而虏等,這兩個(gè)原則都強(qiáng)調(diào)一個(gè)OOP的重要特性--抽象弄唧。
參考書籍
《Android源碼設(shè)計(jì)模式》 何紅輝、關(guān)愛(ài)民著