定義:原件實體(類、模塊、函數等等)應該能夠擴展,可是不可修改編程
public class Calculate { public void operate(int a, int b, String symbol) throws Exception { if (symbol.equals("+")) { System.out.println("結果爲" + (a + b)); } else if (symbol.equals("-")) { System.out.println("結果爲" + (a - b)); } else if (symbol.equals("*")) { System.out.println("結果爲" + a * b); } else if (symbol.equals("/")) { System.out.println("結果爲" + a / b); } else { throw new Exception("非法操做符!"); } } } public class Test { public static void main(String[] args) throws Exception { Calculate c = new Calculate(); c.operate(10, 5, "+");// 結果爲15 c.operate(10, 5, "-");// 結果爲5 c.operate(10, 5, "*");// 結果爲50 c.operate(10, 5, "/");// 結果爲2 c.operate(10, 5, "^");// 此操做爲乘方,拋出異常:非法操做符 } }
結果顯而易見,最開始咱們要作四則運算,後來又想加入乘方運算,因爲程序最初的時候並無考慮到乘方的運算,此時就得更改源代碼;觸類旁通,三角函數的運算怎麼辦?再次違反開放-封閉原則改變源代碼?因此,在需求變化時,一個類(單元,最好具備原子性,也有多是方法)的功能要儘量的惟一,只作一件事。 開放-封閉原則是面向對象設計的核心所在,遵循這個原則能夠避免許多不可避免的麻煩。並且能極大的增長軟件的可擴展性、可維護性和可複用性。
定義:就一個類而言,應該僅有一個引發它變化的緣由ide
仍是四則運算,在這裏咱們把它作一個重構函數
/** * 抽象工廠 */ interface IFactory { Integer result(int a,int b); } /** * 加法工廠 */ class AddFactory implements IFactory { @Override public Integer result(int a,int b) { return a+b; } } /** * 減法工廠 */ class SubFactory implements IFactory { @Override public Integer result(int a, int b) { return a-b; } } /** * 乘法工廠 */ class MulFactory implements IFactory { @Override public Integer result(int a, int b) { return a*b; } } /** * 除法工廠 */ class DivFactory implements IFactory { @Override public Integer result(int a, int b) { return a/b; } } /** * 測試再也不贅述,爲了省事沒有拋異常 :) */ public static void main(String[] args) throws Exception { IFactory factory = new AddFactory(); Integer result = factory.result(10, 5); System.out.println(result);// 15 }
這樣的話,若是再引發需求變更,(假設咱們就是兩個數的運算),直接增長類實現IFactory接口就能夠了,是否是很方便(#^.^#),保證了開放-封閉原則的基礎上,單一職能。測試
定義:
a.高層模塊不該該依賴低層模塊。兩個都應該依賴抽象。
b.抽象不該該依賴細節,細節應該依賴抽象。設計
說白了,要儘可能針對抽象(abstract)類編程,或者針對接口(interface)編程(第二段代碼),不要針對實現編程(第一段代碼)。
再舉個栗子:就拿U盤的插口爲例吧。U盤做爲讀寫信息的一個媒介,須要連入到PC機上,若是全世界不統一爲一個USB接口的話,那麼只作U盤的廠商要針對聯想作一種,Mac作一種,戴爾作一種……想一想都很可怕,因此纔會出現USB接口規範這個抽象的概念,你們針對這個規範製做U盤就能夠了。code
定義:子類型必須可以替換掉他們的父類型對象
public class Father { public void doSome(){ System.out.println("作數學運算"); } } public class Son extends Father { public void method() { System.out.println("作語文運算"); } } public static void main(String[] args) { Father test = new Son(); test.doSome(); }
可能我這裏舉的栗子不太恰當,但也反映出我想表達的意思了;就是說子類所重寫的方法徹底不是父類所須要的方法了,這對客戶端來講是難以想象的。繼承
定義:若是兩個類沒必要彼此直接通訊,那麼這兩個雷就不該當發生直接的相互做用。若是其中一個類須要調用另外一個類的某一個方法的話,能夠經過第三者轉發這個調用。接口
根本思想就是強調了類之間的鬆耦合
舉個栗子:你公司的維修部管維修電子設備,其中一個專人A負責修PC機;你電腦壞了,須要修理,打電話給A,A剛好不在,須要等到A回來才能修電腦,可是你又急用電腦,形成了公司資源的浪費(專人A至關於維修部的一個實例,也就是對象)。
換個角度考慮,公司全部人均可以維修PC機,你直接給維修部打電話,要他們派人過來維修你的電腦(這時候,只是維修部須要關心派誰去維修電腦,你就不須要關心是誰來了)。不針對具體,只針對抽象.資源
定義:一個接口擁有的行爲應該儘量的少
舉個栗子:通常手機只須要知足打電話發短信就OK了,不須要其它額外的行爲;由此能夠衍生出新的接口,智能手機繼承手機,添加新行爲:玩王者榮耀,老年機玩不了王者榮耀,只有如今的智能機才能玩王者榮耀,若是把playKingOfGlory方法做爲Phone接口中的方法就顯得不太合適了。
public interface Phone { void call(); void sendMessage(); } public interface SmartPhone extends Phone{ public void playKingOfGlory(); }