ü
設計原則
2
:針對接口編程而不是針對實現編程。
這裏的接口有多個含義,它能夠是
java
中的
interface
,也能夠是抽象類。
「針對接口編程」,
關鍵就在多態
。利用多態,程序能夠針對超類型編程,執行時會根據實際情況執行到真正的行爲,不會被綁死在超類型的行爲上。「針對超類型編程」這句話,能夠更明確地說成「變量的聲明類型應該是超類型,一般是一個抽象類或者是一個接口,如此,只
要是具體實現此超類型的類所產生的對象,均可以指定給這個變量
。
舉個例子:
假設有一個抽象類
Animal
,其下有兩個實現類
Dog
和
Cat
繼承自
Animal
。作法以下:
²
針對實現編程:
Dog dog = new Dog();
bj.bark();
注:
聲明變量「
dog
」
爲
Dog
類型
(
是
Animal
的具體實現
)
,會形成咱們必須針對具體實現編碼。
²
針對接口
/
抽象類編程
:
Animal animal = new Dog();
Animal.makeSound();
注:利用
animal
進行多態的調用。
設計原則3:多用組合(composition),少用繼承
使用組合創建系統具備很大的彈性,不只可將行爲封裝成類,更能夠「在運行時動態地改變行爲
」
,只要組合的行爲對象符合正確的接口標準便可。
例如:在設計原則一中咱們把「飛行行爲」和「呱呱叫行爲」這兩個變化的行 爲從鴨子類中分離出來。這裏咱們就設計這兩個行爲和鴨子類:
以上 以上爲兩個行爲接口和它的實現類。此時咱們要作的就是把兩個行爲整合到鴨子類中,具體怎麼整合?繼承嗎?繼承只能繼承一個特定的類,所以用繼承將不能「在運行時動態地改變行爲」。那麼咱們選用組合。
在Duck類中「加入兩個實例變量」,分別爲「flyBehavior」與「quackBehavior」,聲明爲接口類型(而不是具體類實現類型),每一個鴨子對象都會動態地設置這些變量以在運行時引用正確的行爲類型(例如:FlyWithWings、Squeak等)。
此時咱們就把兩個行爲組合到
Duck
類中了,既然使用了組合,咱們怎麼
在運行時動態地改變行爲呢?以下咱們寫一個
main
函數來看看:
p
ublic static void mian(String args[]){
Duck duck = new Duck();
duck
.setFlyBehavior(new FlyNoWay());
duck
.setQuackBehavior(new Quack());
//
此時若想要鴨子能飛,咱們能夠經過
setter
方法
在運行時動態地改變行爲
duck.setFlyBehavior(new FlyWithWings());
}
Sping
中依賴注入(IOC)使用的就是組合。