面向?qū)ο笤O(shè)計(jì)思想+六大基本原則

面向?qū)ο蟮母拍?/strong>

萬(wàn)物皆對(duì)象。對(duì)象的實(shí)質(zhì)是屬性和行為。

類(lèi)是具有共同屬性和行為的對(duì)象的集合。類(lèi)定義了對(duì)象的屬性和方法。

面向?qū)ο缶幊桃詫?duì)象和類(lèi)為主體,基本組成要素是類(lèi)和對(duì)象。

類(lèi)

是具有相同特征的對(duì)象的抽象,是一種數(shù)據(jù)類(lèi)型。

基本結(jié)構(gòu)

  • 屬性:對(duì)象數(shù)據(jù)的描述
  • 方法:對(duì)象的行為
  • 構(gòu)造方法:用于實(shí)例化對(duì)象
  • 內(nèi)部類(lèi):在類(lèi)中聲明的類(lèi)(inner class)
  • 塊:分靜態(tài)塊與實(shí)例塊
  • 類(lèi)的聲明:private,default final,abstract,synchronized class 類(lèi)名 { 主體 }

對(duì)象

是客觀實(shí)體的映射,在程序設(shè)計(jì)上對(duì)象是類(lèi)的具體示例

面向?qū)ο笕笠?/strong>

封裝

指利用抽象數(shù)據(jù)類(lèi)型把數(shù)據(jù)和操作封裝在一起,用戶(hù)只能看到對(duì)象的外部信息,對(duì)象的內(nèi)部細(xì)節(jié)是隱藏的。

一方面封裝表示對(duì)象的屬性和方法是一個(gè)整體,是獨(dú)立的,另一方面它表示對(duì)象的內(nèi)部是隱藏的。

可以將青少年封裝成一個(gè)類(lèi),有姓名、性別、年齡的屬性,以及吃、睡的行為,如下:

class Teenagers {

    private String name;
    private String sex;
    private String age;

    public void eat() {
        
    }
        
    public void sleep() {
            
    }
}

繼承

反映了兩個(gè)類(lèi)之間的一種關(guān)系,當(dāng)一個(gè)類(lèi)擁有另一個(gè)類(lèi)的所有屬性和方法時(shí)稱(chēng)這個(gè)類(lèi)繼承了另一個(gè)類(lèi),這兩個(gè)類(lèi)具有繼承的關(guān)系,是一種創(chuàng)建新類(lèi)的機(jī)制.

學(xué)生也是青少年,所以可以繼承青少年的屬性及行為;另一方面,他有自己的屬性和行為。如下,學(xué)生有作業(yè)的屬性,學(xué)習(xí)的行為:

class Student extends Teenagers {
    private Map<String,Object> homework;
    
    public void study() {
        
    }
}

多態(tài)

就是多種狀態(tài),即同一個(gè)實(shí)體具有多種形式。多態(tài)一般在程序運(yùn)行的過(guò)程中表現(xiàn)出來(lái),即同一種類(lèi)型在不同條件下表現(xiàn)不同的結(jié)果。多態(tài)也稱(chēng)為動(dòng)態(tài)綁定,一般在運(yùn)行時(shí)刻才能確定方法的具體執(zhí)行對(duì)象。

實(shí)現(xiàn)多態(tài)的方式:

  1. 方法重寫(xiě)
  2. 方法重載
  3. 父類(lèi)引用指向子類(lèi)對(duì)象

舉例如下:

Teenagers tee = new Student();

以上就是父類(lèi)的引用指向子類(lèi)對(duì)象,指向了Teenager的子類(lèi)對(duì)象Student。

在student中重寫(xiě)eat方法:

class Student extends Teenagers {
    private Map<String,Object> homework;
    
    @Override
    public void eat() {
        System.out.println("peach");
    }
    
    public void study() {
        
    }
}

調(diào)用

tee.eat();

將會(huì)打印出peach。即通過(guò)方法重寫(xiě)的方式實(shí)現(xiàn)了多態(tài)。

面向?qū)ο蟮脑O(shè)計(jì)原則

六大基本原則:

  • 單一職責(zé)原則(Single-Responsibility Principle)
  • 開(kāi)閉原則(Open-Closed Principle)
  • 里氏替換原則(Liskov-Substitution Principle)
  • 接口隔離原則(Interface-Segregation Principle)
  • 依賴(lài)倒置原則(Dependency-Inversion Principle)
  • 迪米特法則(Law of Demeter)

單一職責(zé)原則

  • 基本概念:一個(gè)類(lèi)只負(fù)責(zé)一個(gè)功能領(lǐng)域中的相應(yīng)職責(zé)。就一個(gè)類(lèi)而言,應(yīng)該只有一個(gè)引起它變化的原因。
  • 優(yōu)點(diǎn):
    • 低耦合性,影響范圍小
    • 降低類(lèi)的復(fù)雜度,職責(zé)分明,提高了可讀性
    • 變更引起的風(fēng)險(xiǎn)低,利于維護(hù)

舉例:
對(duì)于一部手機(jī)有打電話,發(fā)短信,觸摸控制等功能

定義接口

    // 接口定義單一職責(zé)
    interface Callable {
        void call();
    }

    interface Touchable {
        void touch();
    }

    interface Message {
        void sendMessage();
    }

    // 接口實(shí)現(xiàn)單一職責(zé)
    class StandardCall implements Callable {
        @Override
        public void call() {
            System.out.println("我要打電話了~");
        }
    }

    class StandardTouch implements Touchable {
        @Override
        public void touch() {
            System.out.println("我要開(kāi)始觸摸操作了~");
        }
    }

    class StandardMessage implements Message {
        @Override
        public void sendMessage() {
            System.out.println("我要發(fā)短信了~");
        }
    }

(上述方式完全依照單一職責(zé)原則,但在實(shí)際應(yīng)用中,多選擇采用針對(duì)方法的單一職責(zé)原則)
產(chǎn)品應(yīng)用

    class Phone implements Callable, Touchable, Message {

        // 無(wú)需重新定義需要有的行為,直接用已有的
        Callable callable = new StandardCall();
        Touchable touchable = new StandardTouch();
        Message message = new StandardMessage();

        @Override
        public void call() {
            callable.call();
        }

        @Override
        public void touch() {
            touchable.touch();
        }

        @Override
        public void sendMessage() {
            message.sendMessage();
        }
    }
    
    public class Demo {

        public static void main(String[] args) {
            Phone phone = new Phone();
            phone.call();
            phone.touch();
            phone.sendMessage();
        }
    }
    

此時(shí)若我們的手機(jī)從電阻觸屏更換到了電容觸屏技術(shù),只需要換掉Touchable實(shí)現(xiàn)類(lèi)中的行為方法體,別的地方都不需要修改

    class StandardTouch implements Touchable {
        @Override
        public void touch() {
            System.out.println("我是新的電容觸摸,我要開(kāi)始觸摸操作了~");
        }
    }

開(kāi)閉原則

  • 概念:一個(gè)軟件實(shí)體(軟件實(shí)體可以指一個(gè)軟件模塊、一個(gè)由多個(gè)類(lèi)組成的局部結(jié)構(gòu)、一個(gè)獨(dú)立的類(lèi)甚至一個(gè)函數(shù))應(yīng)當(dāng)對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。即軟件實(shí)體應(yīng)盡量在不修改原有代碼的情況下進(jìn)行擴(kuò)展。
  • 優(yōu)點(diǎn):
    • 提高系統(tǒng)的靈活性、可復(fù)用性和可維護(hù)性

同樣以手機(jī)為例,我們的手機(jī)擁有自己的屬性和行為,在線下進(jìn)行瘋狂的售賣(mài)中,此時(shí),雙十一來(lái)了,要展開(kāi)一波促銷(xiāo)活動(dòng),但促銷(xiāo)活動(dòng)是暫時(shí)的。

手機(jī)類(lèi)

    // 手機(jī)類(lèi)
    public class SamsungPhone {

        private String model;
        private String color;
        private double price;
    
        public SamsungPhone(String model, String color, double price) {
            this.model = model;
            this.color = color;
            this.price = price;
        }
    
        public String getModel() {
            return model;
        }
    
        public String getColor() {
            return color;
        }
    
        public double getPrice() {
            return price;
        }
    }
    
    //售賣(mài)
    public class Demo {

        public static void main(String[] args) {
            SamsungPhone samsungPhone = new SamsungPhone("Galaxy S8","green",200);
            System.out.println(samsungPhone.getColor() + "的" +samsungPhone.getModel() + "售價(jià)為:" + samsungPhone.getPrice() + "元");
        }
    }
    

雙十一來(lái)臨,開(kāi)閉原則擁抱變化,對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉

// 擴(kuò)展促銷(xiāo)手機(jī)類(lèi)
public class SamsungSale extends SamsungPhone{

    public SamsungSale(String model, String color, double price) {
        super(model, color, price);
    }

    public double getPrice() {
        return super.getPrice() * 0.8;
    }
}

里氏替換原則

  • 概念:強(qiáng)調(diào)的是設(shè)計(jì)和實(shí)現(xiàn)要依賴(lài)于抽象而非具體;子類(lèi)只能去擴(kuò)展基類(lèi),而不是隱藏或者覆蓋基類(lèi)。即設(shè)計(jì)不要破壞繼承關(guān)系。
  • 優(yōu)點(diǎn):
    • 開(kāi)閉原則的體現(xiàn),約束繼承泛濫
    • 提高系統(tǒng)的健壯性、擴(kuò)展性和兼容性

接口隔離原則

  • 概念:接口中的方法應(yīng)該盡量少,不要使接口過(guò)于臃腫;接口盡量細(xì)化。
  • 優(yōu)點(diǎn):
    • 高內(nèi)聚、低耦合
    • 可讀性高、易于維護(hù)

案例:

一水果店的進(jìn)貨出貨收銀系統(tǒng)

違背接口隔離原則(將所有方法都集中在一個(gè)接口類(lèi)中)

public interface FruitStoreInterface {
    /**
     * 計(jì)算價(jià)格
     */
    public void method1();

    /**
     * 收銀
     */
    public void  method2();

    /**
     * 點(diǎn)貨
     */
    public void method3();

    /**
     * 進(jìn)貨
     */
    public void method4();

    /**
     * 出貨
     */
    public void method5();
}

根據(jù)接口隔離原則修改后

// 進(jìn)貨
public interface StockPurchaseInterface {

    /**
     * 點(diǎn)貨
     */
    public void method3();

    /**
     * 進(jìn)貨
     */
    public void method4();
}

// 出貨
public interface OutPurchaseInterface {
    /**
     * 出貨
     */
    public void method5();
}

// 收銀
public interface CalMoneyInterface {
    /**
     * 計(jì)算價(jià)格
     */
    public void method1();

    /**
     * 收銀
     */
    public void  method2();
}

依賴(lài)倒置原則

  • 概念:系統(tǒng)抽象化的具體實(shí)現(xiàn),要求面向接口編程
  • 優(yōu)點(diǎn):
    • 減少類(lèi)間的耦合性,提高系統(tǒng)的穩(wěn)定性
    • 降低并行開(kāi)發(fā)引起的風(fēng)險(xiǎn)
    • 提高代碼的可讀性和可維護(hù)性

案例:

學(xué)生讀書(shū)

違背依賴(lài)倒置原則設(shè)計(jì):

// 學(xué)生類(lèi)
public class Student {

    public void doSomething(YuwenBook book){
        book.readBook();
    }
}

//書(shū)本類(lèi)語(yǔ)文
public class YuwenBook {

    public void readBook(){
        System.out.println("I am reading yuwen book!");
    }
}

//調(diào)用
public class Demo {
    public static void main(String[] args) {
        Student student = new Student();
        YuwenBook yuwenBook = new YuwenBook();
        student.doSomething(yuwenBook);
    }
}

若需求有變,我們不看語(yǔ)文書(shū)了,轉(zhuǎn)看數(shù)學(xué)書(shū),需要改動(dòng)的地方就多了。依照依賴(lài)倒置原則修改如下:

//書(shū)本統(tǒng)一接口類(lèi)
public interface Book {

    public void readBook();
}

//學(xué)生類(lèi)
public class Student {

    public void doSomething(Book book){
        book.readBook();
    }
}

// 語(yǔ)文書(shū)
public class YuwenBook implements Book{

    public void readBook(){
        System.out.println("I am reading yuwen book!");
    }
}

//數(shù)學(xué)書(shū)
public class ShuxueBook implements Book {
    public void readBook() {
        System.out.println("I am reading shuxue book");
    }
}

//調(diào)用
public class Demo {
    public static void main(String[] args) {
        Student student = new Student();
        //讀語(yǔ)文書(shū)
        YuwenBook yuwenBook = new YuwenBook();
        student.doSomething(yuwenBook);

        //讀數(shù)學(xué)書(shū)
        ShuxueBook shuxueBook = new ShuxueBook();
        student.doSomething(shuxueBook);
    }
}

迪米特法則

  • 概念:一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象保持最少的了解;降低系統(tǒng)的耦合度,使一個(gè)模塊的修改盡量少的影響其他模塊,擴(kuò)展會(huì)相對(duì)容易。
  • 優(yōu)點(diǎn):
    • 使軟件有更好的可維護(hù)性和適應(yīng)性
    • 對(duì)象較少依賴(lài)其他對(duì)象的內(nèi)壁結(jié)構(gòu),可以改變對(duì)象容器而不用改變他的調(diào)用者

案例:
朋友A問(wèn)朋友B,朋友C在干嘛,此時(shí)B也不知道,于是,B打電話給C詢(xún)問(wèn)

違背迪米特法則

public class FriendA {

    public String askB(FriendB b) {
        b.call();
        b.sayHello();
        b.askWhere();
        return b.askWhatDo();
    }
}

public class FriendB {

    public void call() {

    }

    public void sayHello() {

    }

    public void askWhere() {

    }

    public String askWhatDo() {
        return "跳繩";
    }
}

根據(jù)迪米特法則,A只想知道C在干嘛,而不用知道B是通過(guò)什么手段或者方式得知C的行為,修改后:

public class FriendA {

    public String askB(FriendB b) {
        return b.call();
    }
}

public class FriendB {

    public String call() {
        sayHello();
        askWhere();
        return askWhatDo();
    }

    private void sayHello() {

    }

    private void askWhere() {

    }

    private String askWhatDo() {
        return "跳繩";
    }
}

結(jié)論:面向?qū)ο蟮脑O(shè)計(jì)原則都是為了擁抱變化而研究出來(lái)的一系列捷徑

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容