Java設計模式
Java設計模式主要原則是開閉原則,即對擴展開放,對修改關閉。由此衍生出5大原則:單一職責原則,里式替換原則,迪米特原則,接口隔離職責,依賴倒置原則。
1、開閉原則
開閉原則:對擴展開放,對修改關閉。一個接口,特別是底層接口或者抽象類,
從誕生后起,要盡可能少改動它,因為一旦改動,所有引用它的類或者接口都會收到影響。需要做回歸測試,所有軟件也需要重新測試。這會帶來巨大的代價。如果知識做擴展,除了擴展新增功能需要做測試外,接口原有實現都不用改動。
單一職責原則
接口或者抽象類職責要單一,不要是很多功能的復合體。比如我有一個用戶接口UserInfo,它既負責維護用戶屬性,也負責定義用戶行為。這就違背了單一職責原則,接口的實現類那必然實現用戶所有功能,后面擴展行為,或者屬性勢必會影響整個接口,影響面也會更大。
里式替換
簡單說就是使用任意子類可以替換父類,程序依然成立,即原有輸入和輸出類型依然不變。
迪米特
Java class要盡可能暴露少的method,field給外部。即多使用private protected 等關鍵字約束訪問權限。同時在編寫程序時 class只和直接接觸的對象有耦合,對于不直接接觸的對象不要產生耦合。示例如下
場景:老師讓那個體育委員清點女生人數
示例一:女生是teacher的參數
public class Teacher {
//老師對學生發布命令,清一下女生
public void commond(GroupLeader groupLeader){
List listGirls = new ArrayList();
//初始化女生
for(int i=0;i<20;i++){
listGirls.add(new Girl());
}
//告訴體育委員開始執行清查任務
groupLeader.countGirls(listGirls);
}
}
示例二:女生作為體育委員的參數
public class Client {
public static void main(String[] args) {
//產生一個女生群體
List<Girl> listGirls = new ArrayList<Girl>();
//初始化女生
for(int i=0;i<20;i++){
listGirls.add(new Girl());
}
Teacher teacher= new Teacher();
//老師發布命令
teacher.commond(new GroupLeader(listGirls));
}
}
通過示例一和二的比較,明顯可以發現示例二有更好的擴展性,老師和女生無直接關系,示例二從老師的角度只知道GroupLeader類,而不需要定義Girl,不管Girl有任何變動,只需要對GroupLeader做相應調整,而teacher不用動。降低耦合,增強擴展性。
接口隔離職責
接口隔離可以看作單一性原則的再度細化,比如上面的UserInfo接口,被拆分為用戶屬性接口和用戶行為接口,用戶行為接口kennel會定義很多行為,打游戲,開車,打球,逛街。等等,這些都屬于用戶行為,但是過多的行為可以再次劃分,讓用戶屬性和各種獨特行為結合變成特定的人,這樣就實現接口隔離。示例待添加。
依賴倒置
先說明依賴正置:如下,張三會開車,因為張三有奔馳,所以方法直接傳入奔馳車。
public class Client {
public static void main(String[] args) {
Driver zhangSan = new Driver();
Benz benz = new Benz();
//張三開奔馳車
zhangSan.drive(benz);
}
}
后面章三買了輛寶馬,但是寶馬和奔馳沒關系,因此張三必須新寫一個方法來實現開寶馬。這種直接傳入實現類的方法沒有擴展性。如果方法參數是car,那么不管張三買幾輛車,都能動態傳入。即面向接口編程,也就是依賴倒置。
依賴倒置做到極限就是控制反轉,如Spring,所有類的創建都是用一套接口,大大降低了耦合性,同時也帶來了對象創建的成本開銷。但由于是啟動創建,因此損耗的是啟動性能,而非運行性能。