一個軟件實體如類、模塊和函數應該`對擴展開放,對修改關閉`。用抽象構建框架,用實現擴展細節。 優勢:提升軟件系統的可複用性以及可維護性
public interface ICourse { Integer getId(); String getName(); Double getPrice(); }
public class JavaCourse implements ICourse{ private Integer Id; private String name; private Double price; public JavaCourse(Integer id, String name, Double price) { this.Id = id; this.name = name; this.price = price; } public Integer getId() { return this.Id; } public String getName() { return this.name; } public Double getPrice() { return this.price; } }
// 若是須要在原有功能基礎上添加一個獲取打折價格的功能,開閉原則建議不要修改原有接口,這裏能夠繼承原有JavaCourse類, // 在原有功能之上擴展 public class JavaDiscountCourse extends JavaCourse { public JavaDiscountCourse(Integer id, String name, Double price) { super(id, name, price); } public Double getDiscountPrice(){ return super.getPrice()*0.8; } }
`高層模塊不該該依賴低層模塊`,兩者都應該依賴其抽象。抽象不該該依賴細節,細節應該依賴抽象。 針對接口編程,不要針對實現編程。 優勢:能夠減小類之間的耦合性,提升系統的穩定性,提升代碼可讀性和可維護性,可下降修改程序所形成的風險。
public interface ICourse { void studyCourse(); } public class JavaCourse implements ICourse { @Override public void studyCourse() { System.out.println("Geely在學習Java課程"); } } public class PythonCourse implements ICourse { @Override public void studyCourse() { System.out.println("Geely在學習Python課程"); } }
public class Geely { public void setiCourse(ICourse iCourse) { this.iCourse = iCourse; } private ICourse iCourse; public void studyImoocCourse() { iCourse.studyCourse(); } }
public class Test { public static void main(String[] args) { Geely geely = new Geely(); geely.setiCourse(new JavaCourse()); geely.studyImoocCourse(); geely.setiCourse(new FECourse()); geely.studyImoocCourse(); } }
不要存在多於一個致使類變動的緣由。一個類/接口/方法只負責一項職責。 優勢:下降類的複雜度、提升類的可讀性、提升系統的可維護性、下降變動引發的風險。
// 不推薦的寫法 public class Bird { public void mainMoveMode(String birdName){ if("鴕鳥".equals(birdName)){ System.out.println(birdName+"用腳走"); }else{ System.out.println(birdName+"用翅膀飛"); } } }
public class FlyBird { public void mainMoveMode(String birdName){ System.out.println(birdName+"用翅膀飛"); } } public class WalkBird { public void mainMoveMode(String birdName){ System.out.println(birdName+"用腳走"); } }
public class Test { public static void main(String[] args) { // 不推薦寫法 Bird bird = new Bird(); bird.mainMoveMode("大雁"); bird.mainMoveMode("鴕鳥"); // 推薦寫法,功能單一 FlyBird flyBird = new FlyBird(); flyBird.mainMoveMode("大雁"); WalkBird walkBird = new WalkBird(); walkBird.mainMoveMode("鴕鳥"); } }
用多個專門的接口,而不使用單一的總接口。客戶端不該該依賴它不須要的接口。 一個類對另外一個類的依賴應該創建在最小的接口上。 創建單一接口,不要創建龐大臃腫的接口。 `儘可能細化接口,接口中的方法儘可能少`。 適度原則,必定要適度。 優勢:符合咱們常說的高內聚低耦合的設計思想,從而使得類具備很好的可讀性、可擴展性和可維護性。
public interface IAnimalAction { void eat(); void fly(); void swim(); } // 將一個接口拆分紅3個接口 public interface IEatAnimalAction { void eat(); } public interface IFlyAnimalAction { void fly(); } public interface ISwimAnimalAction { void swim(); }
public class Dog implements ISwimAnimalAction,IEatAnimalAction { @Override public void eat() { } @Override public void swim() { } }
一個對象應該對其餘對象保持最少的瞭解,又叫最少知道原則。 `儘可能下降類與類之間的耦合`。 優勢:下降類之間的耦合。
public class Boss { public void commandCheckNumber(TeamLeader teamLeader){ teamLeader.checkNumberOfCourses(); } } public class Course { } public class TeamLeader { public void checkNumberOfCourses() { List<Course> courseList = new ArrayList<Course>(); for (int i = 0; i < 20; i++) { courseList.add(new Course()); } System.out.println("在線課程的數量是:" + courseList.size()); } }
public class Test { public static void main(String[] args) { Boss boss = new Boss(); TeamLeader teamLeader = new TeamLeader(); boss.commandCheckNumber(teamLeader); } }
全部引用基類(父類)的地方必須能透明地使用其子類的對象。通俗地講,子類能夠擴展父類的功能,但不能改變父類原有的功能。 里氏替換原則意思說,在軟件中將一個基類對象(父類)替換成它的子類對象,程序將不會產生任何錯誤和異常,反過來則不成立, 若是一個軟件實體使用的是一個子類對象的話,那麼它不必定可以使用基類對象。里氏代換原則是實現開閉原則的重要方式之一, 因爲使用基類對象的地方均可以使用子類對象,所以在程序中儘可能使用基類類型來對對象進行定義,而在程序運行時再肯定其子類 類型,用子類對象來替換父類對象。 例如:我喜歡動物,那我必定喜歡狗,由於狗是動物的子類。可是我喜歡狗,不能據此判定我喜歡動物,由於我並不喜歡老鼠,雖然 它也是動物。
1) `子類能夠實現父類的抽象方法,可是不能覆蓋/重寫父類的非抽象方法`。 2) 子類中能夠增長本身特有的方法。 3) 當子類覆蓋或實現父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬鬆。 4) 當子類的方法實現父類的抽象方法時,方法的後置條件(即方法的返回值)要比父類更嚴格。
參考: Java七大設計原則編程
儘可能使用合成和聚合,而不是集成來達到複用的目的。該原則就是在一個新的對象裏面使用一些已有的對象,使之成爲新對象的 一部分,新的對象經過向這些對象的委派達到複用已有功能的目的。