博客 / 詳情

返回

面向對象設計原則

  1. 開閉原則(Open Closed Principle,OCP):當應用的需求改變時,在不修改軟件實體的源代碼或者二進制代碼的前提下,可以擴展模塊的功能,使其滿足新的需求。

圖1 Windows的桌面主題類圖

  1. 里氏替換原則(Liskov Substitution Principle,LSP):子類可以擴展父類的功能,但不能改變父類原有的功能。也就是説:子類繼承父類時,除添加新的方法完成新增功能外,儘量不要重寫父類的方法。

圖2 “幾維鳥不是鳥”實例的類圖(不符合里氏替換原則)

圖3 “幾維鳥是動物”實例的類圖(合里氏替換原則)

  1. 依賴倒置原則(Dependence Inversion Principle,DIP):高層模塊不應該依賴低層模塊,兩者都應該依賴其抽象;抽象不應該依賴細節,細節應該依賴抽象。其核心思想是:要面向接口編程,不要面向實現編程。

圖4 顧客購物程序的類圖

違反依賴倒置原則代碼(顧客每更換一家商店,都要修改一次代碼,這明顯違背了開閉原則。存在以上缺點的原因是:顧客類設計時同具體的商店類綁定了,這違背了依賴倒置原則):

class Customer{
    public void shopping(ShaoguanShop shop){
        //購物
        System.out.println(shop.sell());
    }
}

class Customer{
    public void shopping(WuyuanShop shop){
        //購物
        System.out.println(shop.sell());
    }
}

修改後的符合依賴倒置原則代碼(定義“婺源網店”和“韶關網店”的共同接口 Shop,顧客類面向該接口編程,其代碼修改如下:):

public class DIPtest{
    public static void main(String[] args){
        Customer wang=new Customer();
        System.out.println("顧客購買以下商品:"); 
        wang.shopping(new ShaoguanShop()); 
        wang.shopping(new WuyuanShop());
    }
}
//商店
interface Shop{
    public String sell(); //賣
}
//韶關網店
class ShaoguanShop implements Shop{
    public String sell(){
        return "韶關土特產:香菇、木耳……"; 
    } 
}
//婺源網店
class WuyuanShop implements Shop{
    public String sell(){
        return "婺源土特產:綠茶、酒糟魚……"; 
    }
} 
//顧客
class Customer{
    public void shopping(Shop shop){
        //購物
        System.out.println(shop.sell()); 
    }
}
  1. 單一職責原則(Single Responsibility Principle,SRP):單一職責原則規定一個類應該有且僅有一個引起它變化的原因,否則類應該被拆分

圖5 大學學生工作管理程序的類圖

  1. 接口隔離原則(Interface Segregation Principle,ISP):要為各個類建立它們需要的專用接口,而不要試圖去建立一個很龐大的接口供所有依賴它的類去調用。

圖6 學生成績管理程序的類圖

  1. 迪米特法則(Law of Demeter,LoD)又叫作最少知識原則(Least Knowledge Principle,LKP):如果兩個軟件實體無須直接通信,那麼就不應當發生直接的相互調用,可以通過第三方轉發該調用。其目的是降低類之間的耦合度,提高模塊的相對獨立性。迪米特法則中的“朋友”是指:當前對象本身、當前對象的成員對象、當前對象所創建的對象、當前對象的方法參數等,這些對象同當前對象存在關聯、聚合或組合關係,可以直接訪問這些對象的方法。

圖7 明星與經紀人的關係圖

public class LoDtest{
    public static void main(String[] args){
        Agent agent=new Agent();
        agent.setStar(new Star("林心如"));
        agent.setFans(new Fans("粉絲韓丞"));
        agent.setCompany(new Company("中國傳媒有限公司"));
        agent.meeting();
        agent.business();
    }
}
//經紀人
class Agent{
    private Star myStar;
    private Fans myFans;
    private Company myCompany;
    public void setStar(Star myStar){
        this.myStar=myStar;
    }
    public void setFans(Fans myFans){
        this.myFans=myFans;
    }
    public void setCompany(Company myCompany){
        this.myCompany=myCompany;
    }
    public void meeting(){
        System.out.println(myFans.getName()+"與明星"+myStar.getName()+"見面了。");
    }
    public void business(){
        System.out.println(myCompany.getName()+"與明星"+myStar.getName()+"洽淡業務。");
    }
}
//明星
class Star{
    private String name;
    Star(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
}
//粉絲
class Fans{
    private String name;
    Fans(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
}
//媒體公司
class Company{
    private String name;
    Company(String name){
        this.name=name;
    }
    public String getName(){
        return name;
    }
}
  1. 合成複用原則(Composite Reuse Principle,CRP)又叫組合/聚合複用原則(Composition/Aggregate Reuse Principle,CARP):它要求在軟件複用時,要儘量先使用組合或者聚合等關聯關係來實現,其次才考慮使用繼承關係來實現。

圖8 用繼承關係實現的汽車分類的類圖(不符合合成複用原則)

圖9 用組合關係實現的汽車分類的類圖(符合合成複用原則)

開閉原則是總綱,它告訴我們要對擴展開放,對修改關閉;里氏替換原則告訴我們不要破壞繼承體系;依賴倒置原則告訴我們要面向接口編程;單一職責原則告訴我們實現類要職責單一;接口隔離原則告訴我們在設計接口的時候要精簡單一;迪米特法則告訴我們要降低耦合度;合成複用原則告訴我們要優先使用組合或者聚合關係複用,少用繼承關係複用。

user avatar lankerens 頭像 markerhub 頭像 fulng 頭像 edagarli 頭像 deltaf 頭像 tracy_5cb7dfc1f3f67 頭像 goudantiezhuerzi 頭像 buxiyan 頭像 async_wait 頭像 thinkfault 頭像 nahandechaomian 頭像 chengxuyuanxiaohui 頭像
12 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.