天天看點

設計模式之面向對象與類基礎特征概念

PS一句:最終還是選擇CSDN來整理發表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支援MarkDown文法了,牛逼啊!

背景知識

設計模式(Design pattern)是一套被反複使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人了解、保證代碼可靠性。 毫無疑問,設計模式于己于他人于系統都是多赢的;設計模式使代碼編制真正工程化;設計模式是軟體工程的基石脈絡,如同大廈的結構一樣。

這是官方的專業解釋。大白話意思就是說設計模式就經驗的總結,模闆的運用。

設計模式之面向對象與類基礎特征概念

面向對象三大基本特性

封裝

封裝是把過程和資料包圍起來,對資料的通路隻能通過已定義的界面。

繼承

繼承是一種類的層次模型,并且允許和鼓勵類的重用,它提供了一種明确表述共性的方法。

多态

多态性是指允許不同類的對象對同一消息作出響應。多态性包括編譯時多态和運作時多态。

主要作用就是用來将接口和實作分離開,改善代碼的組織結構,增強代碼的可讀性。

在某些很簡單的情況下,或許我們不使用多态也能開發出滿足我們需要的程式,但大多數情況,如果沒有多态,就會覺得代碼極其難以維護。

面向對象通過類和對象來實作抽象,實作時誕生了三個重要的特性,也就是由于這三個特性才衍生出了各種各樣的設計模式。

面向對象類關系

通過大量代碼和經驗可以得知,類與類之間主要有6種關系模式,這六種模闆寫法導緻了平時書寫代碼的不同耦合度。具體如下所列(耦合度依次增強排列):

  1. 依賴關系
  2. 關聯關系
  3. 聚合關系
  4. 組合關系
  5. 繼承關系
  6. 實作關系

為了記住類與類之間的關系,我自己總結了一句話友善記憶:《衣(依賴)冠(關聯)劇(聚合)組(組合)紀(繼承)實(實作)》。

依賴關系

一般而言,依賴關系在Java語言中展現為局域變量、方法的形參,或者對靜态方法的調用。

如下就是一個簡單的例子:

package yanbober.github.io;

class Code {
    public void coding(String str) {
        System.out.println("Coding with "+ str +" !");
    }
}

class ProgramMonkey {
    public void programAndroid(Code code) {
        code.coding("Java/Android");
    }

    public void programIOS(Code code) {
        code.coding("OC/IOS");
    }

    public void programPHP(Code code) {
        code.coding("PHP");
    }
}

public class Main {
    public static void main(String[] args) {
        ProgramMonkey monkey = new ProgramMonkey();
        Code code = new Code();
        monkey.programAndroid(code);
        monkey.programIOS(code);
        monkey.programPHP(code);
    }
}
           

關聯關系

使一個類知道另一個類的屬性和方法。關聯可以是雙向的,也可以是單向的。在Java語言中,關聯關系一般使用成員變量來實作。

如下就是一個簡單的例子:

package yanbober.github.io;

class Code {
    public void coding(String str) {
        System.out.println("Coding with "+ str +" !");
    }
}

class ProgramMonkey {
    private Code mCode;

    public ProgramMonkey(Code mCode) {
        this.mCode = mCode;
    }
    //成員變量關聯
    public void programAndroid() {
        mCode.coding("Java/Android");
    }
    //形參關聯
    public void programIOS(Code code) {
        code.coding("OC/IOS");
    }
}

public class Main {
    public static void main(String[] args) {
        ProgramMonkey monkey = new ProgramMonkey(new Code());
        Code code = new Code();
        monkey.programAndroid();
        monkey.programIOS(code);
    }
}
           

使用方法參數形式可以表示依賴關系,也可以表示關聯關系。其實在本質上他們是由關系的。在本例中,使用成員變量意思是代碼是我自己寫的,我具備這些文法技能,能寫出來代碼。使用方法參數意思是IOS代碼不是我自己寫的,我隻是個闆磚碼農,别人寫好是啥樣我抄啥樣。

聚合關系

聚合是關聯關系的一種,是強的關聯關系,聚合是整體和個體之間的關系。與關聯關系一樣,聚合關系也是通過執行個體變量實作的,但是關聯關系所涉及的兩個類是處在同一層次上的,而在聚合關系中,兩個類是處在不平等層次上的,一個代表整體,另一個代表部分。

如下就是一個簡單的例子:

package yanbober.github.io;

class Code {
    public void coding(String str) {
        System.out.println("Coding with "+ str +" !");
    }
}

class ProgramMonkey {
    private Code mCode;

    public Code getmCode() {
        return mCode;
    }

    public void setmCode(Code mCode) {
        this.mCode = mCode;
    }

    public ProgramMonkey() {
    }
    //也是聚合關系
    public void programAndroid() {
        mCode.coding("Java/Android");
    }
}

public class Main {
    public static void main(String[] args) {
        ProgramMonkey monkey = new ProgramMonkey(new Code());
        monkey.programAndroid();
    }
}
           

本例的意思就是說寫程式是Monkey的一項技能。聚合關系一般使用setter方法給成員變量指派。

組合關系

組合是關聯關系的一種,是比聚合關系強的關系。它要求普通的聚合關系中代表整體的對象負責代表部分對象的生命周期,組合關系是不能共享的。代表整體的對象需要負責保持部分對象和存活,在一些情況下将負責代表部分的對象湮滅掉。代表整體的對象可以将代表部分的對象傳遞給另一個對象,由後者負責此對象的生命周期。換言之,代表部分的對象在每一個時刻隻能與一個對象發生組合關系,由後者排他地負責生命周期。部分和整體的生命周期一樣。

如下就是一個簡單的例子:

package yanbober.github.io;

class Code {
    public void coding(String str) {
        System.out.println("Coding with "+ str +" !");
    }
}

class ProgramMonkey {
    private Code mCode;

    public ProgramMonkey(Code mCode) {
        this.mCode = mCode;
    }

    public void programAndroid() {
        mCode.coding("Java/Android");
    }
}

public class Main {
    public static void main(String[] args) {
        ProgramMonkey monkey = new ProgramMonkey(new Code());
        monkey.programAndroid();
    }
}
           

意思就是說想要成為ProgramMonkey程式猿,你必須具備Code程式設計能力,沒有程式設計能力,是毛程式員啊(餓死了);我要是轉行了,誰也拿不走我的Code技能;我的技能跟随我的生命,我挂了技能也沒了,技能沒了,我就挂了!是以說為了表示組合關系,常常會使用構造方法來達到初始化的目的。

繼承關系

繼承表示類與類(或者接口與接口)之間的父子關系。

如下就是一個簡單的例子:

package yanbober.github.io;

class Monkey {
    public void run() {
        System.out.println("I can run!");
    }
}

class ProgramMonkey extends Monkey{
    public void program() {
        System.out.println("I can Program!");
    }
}

public class Main {
    public static void main(String[] args) {
        ProgramMonkey monkey = new ProgramMonkey();
        monkey.run();
        monkey.program();
    }
}
           

如上的意思就是說一開始Monkey猴子隻會跑,後來進化成了ProgramMonkey程式猿,具備了新的program技能。也就是說程式猿具備了兩項技能。

實作關系

接口定義好操作的集合,由實作類去完成接口的具體操作。

如下就是一個簡單的例子:

package yanbober.github.io;

interface CodeInterface {
    void code();
}

class ProgramMonkey implements CodeInterface {
    public void run() {
        System.out.println("I can run!");
    }

    @Override
    public void code() {
        System.out.println("I can coding!");
    }
}

public class Main {
    public static void main(String[] args) {
        ProgramMonkey monkey = new ProgramMonkey();
        monkey.run();
        monkey.code();
    }
}
           

意思就是說,有一個Code的技能,誰想學習擁有這個技能誰就實作它,我實作了他,我也就具備技能了!

關聯、聚合、組合隻能配合語義,結合上下文才能夠判斷出來,而隻給出一段代碼讓我們判斷是關聯,聚合,還是組合關系,則是無法判斷的。

面向對象七大基本原則

在運用面向對象的思想進行軟體設計時,需要遵循的原則一共有7個,他們是:

  1. 單一職責原則(Single Responsibility Principle)
  2. 裡氏替換原則(Liskov Substitution Principle)
  3. 依賴倒置原則(Dependence Inversion Principle)
  4. 接口隔離原則(Interface Segregation Principle)
  5. 迪米特法則(Law Of Demeter)
  6. 開閉原則(Open Close Principle)
  7. 組合/聚合複用原則(Composite/Aggregate Reuse Principle CARP)

在軟體設計的過程中,隻要我們盡量遵循以上七條設計原則,設計出來的軟體一定會是一個優秀的軟體,它必定足夠健壯、足夠穩定,并以極大的靈活性來迎接随時而來的需求變更等因素。

關于這七大基本原則是一個很深的話題,後續會分析學習七項基本原則。

【工匠若水 http://blog.csdn.net/yanbober】 繼續閱讀《設計模式之面向對象七大基本原則》 http://blog.csdn.net/yanbober/article/details/45312243