理解面向?qū)ο?/h2>

面向?qū)ο笫且环N軟件開(kāi)發(fā)的方法,同類(lèi)的還有面向過(guò)程。
面向?qū)ο笾傅氖窃诔绦蛟O(shè)計(jì)中采用Java的封裝、繼承、多態(tài)、六大原則特性來(lái)設(shè)計(jì)代碼。
它其實(shí)考驗(yàn)的是你審視代碼的角度,運(yùn)用這些特性,可以寫(xiě)出讓人賞心悅目、簡(jiǎn)單易懂的代碼。
不運(yùn)用這些特性當(dāng)然也可以進(jìn)行開(kāi)發(fā)。不過(guò)代碼的可讀性、擴(kuò)展性、靈活性等會(huì)大大下降,冗余度、維護(hù)成本等會(huì)大大上升。

封裝

  1. 概念
    在Java中,封裝就是將一些通用、常用的功能方法寫(xiě)到一個(gè)新類(lèi)中,那么當(dāng)我們用到這些功能時(shí),直接去調(diào)用這個(gè)新類(lèi)中的方法即可。這就像是有一個(gè)人A,他擁有一些技能,當(dāng)我用到這些技能時(shí),不需要自己去學(xué)習(xí)這些技能,只需要去找A即可。
  2. 優(yōu)點(diǎn)
    提高代碼的重用,減少重復(fù)代碼,提高代碼的可讀性、方便理解。而且封裝的思想也對(duì)應(yīng)了Java中一處編程,到處執(zhí)行的思想。
  3. 實(shí)例
    實(shí)例就不用多說(shuō)了,平時(shí)寫(xiě)代碼我們總會(huì)自己創(chuàng)建一個(gè)utils包,存放一些自己或者別人寫(xiě)的utils類(lèi)。

繼承

  1. 概念
    繼承是從已有的類(lèi)中派生出新的類(lèi),新的類(lèi)能吸收已有類(lèi)的數(shù)據(jù)屬性和行為,并能擴(kuò)展新的能力(來(lái)自百度百科)。
    這種官方語(yǔ)言太難講,而且各位看官也看著費(fèi)勁。我還是直接說(shuō)自己的理解吧。
    首先繼承的含義,就是一直我們口中所說(shuō)的父類(lèi)(基類(lèi))和子類(lèi)。子類(lèi)通過(guò)關(guān)鍵字extends繼承父類(lèi),就可以擁有父類(lèi)的非私有的屬性和方法。
    在Java中,繼承是單一繼承+多層繼承的。
  2. 優(yōu)點(diǎn)
    提高代碼的重用,減少重復(fù)的代碼。增加了軟件開(kāi)發(fā)的靈活性。
  3. 缺點(diǎn)
    由于多層繼承的存在,所以無(wú)限使用繼承特性的話(huà),會(huì)造成子類(lèi)的過(guò)度冗余。

多態(tài)

  1. 概念
    多態(tài)指的是同一個(gè)方法,會(huì)因?yàn)閷?duì)象的不同導(dǎo)致不同的結(jié)果。
    沒(méi)錯(cuò),就是這樣!

    多態(tài)的三要素一定要知道。這個(gè)東西理解了自然就記住了。
    繼承、重寫(xiě)、父類(lèi)的引用指向子類(lèi)的對(duì)象
    具體含義,還是在后面舉個(gè)栗子來(lái)解釋一下。
  2. 優(yōu)點(diǎn)
    增加了軟件開(kāi)發(fā)的靈活性,簡(jiǎn)化了編程和修改過(guò)程。
  3. 實(shí)例
    首先我們定義了一個(gè)汽車(chē)接口Car,接口中有一個(gè)方法用來(lái)獲取車(chē)的類(lèi)型:
    public interface Car {
    
        String getCarType();
    }
    

接下來(lái),我們創(chuàng)建了蘭博基尼,以及五菱宏光實(shí)現(xiàn)了這個(gè)接口。
五菱宏光:

 public class WuLingHongGuang implements Car {
  @Override
   public String getCarType() {
      return "五菱宏光";
     }
 }

蘭博基尼:

    public class LanBoJiNi implements Car {
        @Override
        public String getCarType() {
            return "蘭博基尼";
        }
    }

接下來(lái),我們利用多態(tài)的特性,來(lái)創(chuàng)建并執(zhí)行接下來(lái)的代碼:

     public static void main(String[] args){
         Car car1 = new LanBoJiNi();
         Car car2 = new WuLingHongGuang();

         System.out.println("車(chē)1的類(lèi)型:"+car1.getCarType());
         System.out.println("車(chē)2的類(lèi)型:"+car2.getCarType());
     }

可以看到控制臺(tái)的結(jié)果:

    車(chē)1的類(lèi)型:蘭博基尼
    車(chē)2的類(lèi)型:五菱宏光
  1. 總結(jié)
    通過(guò)實(shí)例,再結(jié)合多態(tài)三要素:繼承、重寫(xiě)、父類(lèi)的引用指向子類(lèi)的對(duì)象。
    蘭博基尼和五菱宏光實(shí)現(xiàn)了Car接口(繼承),重寫(xiě)了Car中的getCarType()(重寫(xiě)),接下來(lái)最關(guān)鍵的要素,我們用父類(lèi)的引用,創(chuàng)建子類(lèi)的對(duì)象。

    那么接下來(lái),當(dāng)你去調(diào)用getCarType()時(shí),Java會(huì)首先調(diào)用子類(lèi)中的getCarType(),而不是父類(lèi)Car中的。
    其實(shí)這個(gè)實(shí)例,并不能幫你很好地理解多態(tài)。它只是很生硬地運(yùn)用了多態(tài)的特性。在項(xiàng)目中運(yùn)用多態(tài)非常的重要,這個(gè)需要自己實(shí)戰(zhàn)才能好好理解。

六大原則

六大原則包括:?jiǎn)我宦氊?zé)、開(kāi)閉、里氏替換、依賴(lài)倒置、接口隔離、迪米特。接下來(lái)我們一個(gè)一個(gè)來(lái)理解這些原則的思想。

單一職責(zé)原則(Single Responsibility Principle)

  1. 概念
    就一個(gè)類(lèi)而言,應(yīng)該僅有一個(gè)引起它變化的原因。
    非常容易理解的一個(gè)原則,并且非常重要!但這個(gè)原則是一個(gè)備受爭(zhēng)議的原則,和別人爭(zhēng)論這個(gè)原則,是屢試不爽的。

    因?yàn)閱我宦氊?zé)原則劃分界限并不總是那么清晰,更多的時(shí)候是根據(jù)個(gè)人經(jīng)驗(yàn)來(lái)界定的。

開(kāi)閉原則(Open Close Principle)

  1. 概念
    就一個(gè)類(lèi)或方法而言,應(yīng)該對(duì)于擴(kuò)展是開(kāi)放的,對(duì)于修改是關(guān)閉的。
    軟件也有自己的生命周期,越往后迭代,代碼越多,冗余度也會(huì)隨之提升,維護(hù)成本也就越來(lái)越高,可能一次不經(jīng)意地bug修改就會(huì)破壞之前已經(jīng)通過(guò)測(cè)試的代碼。因此,當(dāng)軟件需要變化時(shí),我們應(yīng)該通過(guò)擴(kuò)展的方式去實(shí)現(xiàn),而不是通過(guò)修改原有代碼來(lái)實(shí)現(xiàn)。
    當(dāng)然,這是理想愿景,在實(shí)際開(kāi)發(fā)中往往是擴(kuò)展修改同時(shí)存在的,因?yàn)樵俸玫拇a,終有一天也會(huì)有無(wú)法適應(yīng)的場(chǎng)景出現(xiàn)。所以,我們要做的,就是在開(kāi)發(fā)新東西的時(shí)候,盡可能地考慮多的場(chǎng)景,盡可能降低修改的可能性。并且當(dāng)我們發(fā)現(xiàn)代碼有“腐朽”的味道時(shí),應(yīng)該盡早地進(jìn)行代碼重構(gòu),使代碼恢復(fù)到正常的“進(jìn)化”過(guò)程。

里氏替換原則(Liskov Substitution Principle)

  1. 概念
    所有引用父類(lèi)的地方,都可以透明的傳遞子類(lèi)對(duì)象。
    這個(gè)原則簡(jiǎn)直就是多態(tài)的完美體現(xiàn)。
    這個(gè)原則強(qiáng)調(diào)的是運(yùn)用多態(tài)時(shí),應(yīng)該注子類(lèi)的適配,使之無(wú)論傳遞任何子類(lèi)對(duì)象,都能完美適應(yīng)父類(lèi)引用,不會(huì)產(chǎn)生異常。
  2. 實(shí)例
    我們繼續(xù)引用多態(tài)的那個(gè)實(shí)例,在那個(gè)實(shí)例之上做些修改。
    現(xiàn)在我們是汽車(chē)制造商,你只需要告訴我品牌,我就可以生產(chǎn)出對(duì)應(yīng)品牌的車(chē)。
    我們目前只能生產(chǎn)蘭博基尼五菱宏光,那么接下來(lái)我們改變一下main方法,生產(chǎn)一下這2輛車(chē):
public static void main(String[] args) {
  //創(chuàng)建蘭博基尼
  System.out.println("生產(chǎn)了一輛:" + createCar(new LanBoJiNi()));
  //創(chuàng)建五菱宏光
  System.out.println("生產(chǎn)了一輛:" + createCar(new WuLingHongGuang()));
}

private static String createCar(Car car) {
  return car.getCarType();
}

上面當(dāng)中,我們通過(guò)createCar(Car car)來(lái)創(chuàng)建了蘭博基尼五菱宏光,雖然createCar()要求的參數(shù)是Car,但是我們傳入了子類(lèi)對(duì)象蘭博基尼五菱宏光。并且這2個(gè)類(lèi)都做了很好的適配(一個(gè)栗子而已,大家就認(rèn)為其實(shí)我的蘭博基尼其實(shí)是經(jīng)過(guò)500道獨(dú)特工序才制造出來(lái)的,五菱宏光是另外的500道工序),無(wú)論我傳入誰(shuí),都可以完美生產(chǎn),不會(huì)產(chǎn)生異常。這就是里氏替換原則!

依賴(lài)倒置原則(Dependence Inversion Principle)

  1. 概念
    依賴(lài)倒置原則指代了一種特定的解耦形式,使得高層次的模塊不依賴(lài)低層次的模塊去實(shí)現(xiàn)細(xì)節(jié)。主要關(guān)鍵點(diǎn)有以下3點(diǎn):
  • 高層模塊不應(yīng)該依賴(lài)低層模塊,兩者都應(yīng)該依賴(lài)其抽象。

  • 抽象不應(yīng)該依賴(lài)細(xì)節(jié)。

  • 細(xì)節(jié)應(yīng)該依賴(lài)細(xì)節(jié)。

    在Java語(yǔ)言中,抽象指的就是接口或抽象類(lèi),兩者都是不能直接被實(shí)例化的;細(xì)節(jié)就是實(shí)現(xiàn)類(lèi),實(shí)現(xiàn)接口或者繼承抽象類(lèi)而產(chǎn)生的類(lèi)就是細(xì)節(jié),可以直接被實(shí)例化。高層模塊就是抽象,底層模塊就是具體實(shí)現(xiàn)類(lèi)。一句話(huà)概括的話(huà)就是:面向接口編程。面向接口編程是面向?qū)ο蟮木柚弧?/p>

接口隔離原則(Interface Segregation Principles)

  1. 概念
    類(lèi)不應(yīng)該依賴(lài)它不需要的接口。
    另一種定義是:類(lèi)依賴(lài)的接口都應(yīng)該是最小單位。
    那么接口隔離原則其實(shí)就是要求我們將龐大、臃腫的接口按照某種規(guī)則,將其拆封成更小的、更具體的接口,這樣客戶(hù)端只需要依賴(lài)它需要的接口即可。
    接口隔離原則的目的就是使系統(tǒng)解耦,從而更容易進(jìn)行重構(gòu)、更改等操作。

迪米特原則(Law of Demeter)

  1. 概念
    一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有最少的依賴(lài)。
    通俗地講,一個(gè)類(lèi)應(yīng)該對(duì)自己需要耦合或調(diào)用的類(lèi)知道得最少,類(lèi)的內(nèi)部如何實(shí)現(xiàn)與調(diào)用者或者依賴(lài)者沒(méi)關(guān)系,調(diào)用者或依賴(lài)者只需要知道它需要的方法即可,其他的一概不用管。
    如果兩個(gè)對(duì)象的關(guān)系過(guò)于密切,那么當(dāng)一個(gè)對(duì)象發(fā)生變化時(shí),另一個(gè)對(duì)象就會(huì)產(chǎn)生不可預(yù)估的風(fēng)險(xiǎn)。

小結(jié)

在應(yīng)用的開(kāi)發(fā)過(guò)程中,最難的不是完成應(yīng)用的開(kāi)發(fā)工作,而是在后續(xù)的升級(jí)、維護(hù)過(guò)程中讓?xiě)?yīng)用系統(tǒng)能夠擁抱變化。擁抱變化也就意味著在滿(mǎn)足需求且不破壞系統(tǒng)穩(wěn)定性的前提下保持高擴(kuò)展性、高內(nèi)聚、低耦合,在經(jīng)歷了各版本的變更之后依然保持清晰、靈活、穩(wěn)定的系統(tǒng)架構(gòu)。
當(dāng)然這是一個(gè)理想的情況,但我們必須要朝著這個(gè)方向去努力,那么遵循面向?qū)ο笏枷刖褪俏覀冏呦蚶硐氲牡谝徊健?/p>

感謝

  1. 《Android源碼設(shè)計(jì)模式解析與實(shí)戰(zhàn)》 何紅輝、關(guān)愛(ài)民 著
  2. 百度百科
最后編輯于
?著作權(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)容