面向對象設計的三大特點與五大基本原則


面向對象設計

一、面向對象設計的三個基本要素

面向對象的三個基本特征是:封裝、繼承、多態。

1. 封裝性

封裝是一種信息隱蔽技術,他體現於類的說明,是都西昂重要的特性。

封裝使得數據和操作數據的方法封裝成一個整體,想成為獨立性很強的模塊,使得用戶只能看到對象的外部特征,內部是看不到的。

簡而言之就是說,封裝使對象的設計者與對象的使用者分開,使用者只要知道對象可以做什么就可以了,無需知道具體是怎么實現的。借助封裝有助於提高類和系統的安全性。

例:屬性私有,get/set方法,有參構造 ,方法

2.繼承性

繼承是一種由已有類創建子類的機制,利用繼承,可以先創建一個共有屬性的一般類,根據這個類再創建具有特殊屬性的子類,被繼承的類成為父類,當然子類也可以成為父類來繼續向下擴展。

例:子承父類

3.多態

同一個信息被不同的對象接收到時可能產生不同的行為,這就是多態性。有繼承(接口)有重寫,父類引用指向子類對象,就會產生多態。多態可以改善程序的組織架構,提高程序的可擴展性。

例:父類指向子類對象,子類重寫父類方法

二、面向對象設計的五個基本設計原則

面向對象設計的五個基本設計原則是:單一職責原則、開放封閉原則、里氏替換原則、依賴倒置原則、接口隔離原則

1.單一職責原則

就一個類而言,應該只專注於做一件事和僅有一個引起它變化的原因。

也可以理解為引用變化的原因,當你發現有兩個變化會要求我們修改這個類,那么你就要考慮撤分這個類了。因為職責是變化的一個軸線,當需求變化時,該變化會反映類的職責的變化。

“就像一個人身兼數職,而這些事情相互關聯不大,甚至有沖突,那他就無法很好的解決這些職責,應該分到不同的人身上去做才對。”

interface Modem//
{
    public void dial(string pno);//撥號
    public void hangup();//掛斷
    public void send(char c);//發送
    public void recv();//接受
}
//應改為
interface DataChannel//數據通道
{
    public void send(char c);
    public void recv();
}
interface Connection//鏈接
{
    public void dial(string pno);
    public void hangup();
}

 

優點:消除耦合,減小因需求變化引起代碼僵化

2·開放封閉原則

其核心思想是:軟件實體應該是可擴展的,而不可修改的。也就是,對擴展開放,對修改封閉。開放封閉原則主要體現在兩個方面 1、對擴展開放,意味着有新的需求或者變化時,可以對現有代碼進行擴展,以適應新的情況。 2、對修改封閉,意味着一旦設計完成,就可以獨立完成其工作,而不要對其進行任何嘗試的修改。

public interface Bark {
    public void bark();
}
public class Awaw implements Bark{
    @Override
    public void bark() {
        System.out.println("嗷嗷~~");
    }
}
public class Zhazha implements Bark{
    @Override
    public void bark() {
        System.out.println("喳喳~~");
    }
}
public abstract class Bird {
    //聲明屬性
    private Bark bark;//接口的對象
    //設置set屬性
    public void setBark(Bark bark) {
        this.bark = bark;
    }
    /**
     * 鳥叫的方法
     */
    public void birdBark(){
        bark.bark();
    }
}
public class Test {
    public static void main(String[] args) {
        //測試
        //聲明鳥的叫聲
        Bark awaw = new Awaw();
        Bark zhazha = new Zhazha();
        //bird對象
        Bird rocketBird = new RocketBird();
        rocketBird.setBark(awaw);
        Bird splitBird = new SplitBird();
        splitBird.setBark(zhazha);
    }
}

 

優點:

1、降低程序各部分之間的耦合性,使程序模塊互換成為可能; 2、使軟件各部分便於單元測試,通過編制與接口一致的模擬類(Mock),可以很容易地實現軟件各部分的單元測試; 3、利於實現軟件的模塊的呼喚,軟件升級時可以只部署發生變化的部分,而不會影響其它部分;

3·里氏替換原則

核心思想:子類必須能夠替換其父類。這一思想體現為對繼承機制的約束規范,只有子類能夠替換父類時才能保證系統在運行期內識別子類,這是保證繼承復用的基礎。在父類和子類的具體行為中,必須嚴格把握繼承層次中的關系和特征,將父類替換為子類,程序的行為不會發生任何變化。同時,這一約束反過來則是不成立的,子類可以替換父類,但是父類不一定能替換子類。

對於這個原則,通俗一些的理解就是,父類的方法都要在子類中實現或者重寫。

public abstract class Bird {
    /**
     * 飛的方法
     */
    void fly(){
        System.out.println("彈跳-飛");
    }
    /**
     * 叫的方法
     */
    void call(){
        System.out.println("嗷~!");
    }
    /**
     * 攻擊的抽象方法
     */
    abstract void attack();
}
public class RocketBird extends Bird {
    @Override
    void attack() {
        System.out.println("加速沖刺");
    }
}
public class SplitBird extends Bird{
​
    @Override
    void attack() {
        System.out.println("分裂攻擊");
    }
}
public class Test {
    public static void main(String[] args) {
        Bird splitBird = new SplitBird();
        Bird rocketBird = new RocketBird();
        splitBird.attack();
        rocketBird.attack();
    }
}

 

優點:

1、保證系統或子系統有良好的擴展性。只有子類能夠完全替換父類,才能保證系統或子系統在運行期內識別子類就可以了,因而使得系統或子系統有了良好的擴展性。 2、實現運行期內綁定,即保證了面向對象多態性的順利進行。這節省了大量的代碼重復或冗余。避免了類似instanceof這樣的語句,或者getClass()這樣的語句,這些語句是面向對象所忌諱的。 3、有利於實現契約式編程。契約式編程有利於系統的分析和設計,指我們在分析和設計的時候,定義好系統的接口,然后再編碼的時候實現這些接口即可。在父類里定義好子類需要實現的功能,而子類只要實現這些功能即可。

4·依賴倒置原則

其核心思想是:依賴於抽象。具體而言就是高層模塊不依賴於底層模塊,二者都同依賴於抽象;抽象不依賴於具體,具體依賴於抽象。

反面例子:

img 缺點:耦合太緊密,Light發生變化將影響ToggleSwitch。

解決方法:

img

優點:更為通用、更為穩定。

優點:

使用傳統過程化程序設計所創建的依賴關系,策略依賴於細節,這是糟糕的,因為策略受到細節改變的影響。依賴倒置原則使細節和策略都依賴於抽象,抽象的穩定性決定了系統的穩定性。

5·接口隔離原則

其核心思想是:使用多個小的專門的接口,而不要使用一個大的總接口。

“不應該強迫客戶依賴於它們不用的方法。接口屬於客戶,不屬於它所在的類層次結構。”

img

img

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM