設(shè)計(jì)模式篇

背景

最近在準(zhǔn)備面試,結(jié)合之前的工作經(jīng)驗(yàn)和近期在網(wǎng)上收集的一些面試資料,準(zhǔn)備將Android開發(fā)崗位的知識(shí)點(diǎn)做一個(gè)系統(tǒng)的梳理,整理成一個(gè)系列:Android應(yīng)用開發(fā)崗 面試匯總。本系列將分為以下幾個(gè)大模塊:
Java基礎(chǔ)篇、Java進(jìn)階篇、常見設(shè)計(jì)模式
Android基礎(chǔ)篇Android進(jìn)階篇、性能優(yōu)化
網(wǎng)絡(luò)相關(guān)、數(shù)據(jù)結(jié)構(gòu)與算法
常用開源庫、Kotlin、Jetpack

注1:以上文章將陸續(xù)更新,直到我找到滿意的工作為止,有跳轉(zhuǎn)鏈接的表示已發(fā)表的文章。
注2:該系列屬于個(gè)人的總結(jié)和網(wǎng)上東拼西湊的結(jié)果,每個(gè)知識(shí)點(diǎn)的內(nèi)容并不一定完整,有不正確的地方歡迎批評(píng)指正。
注3:部分摘抄較多的段落或有注明出處。如有侵權(quán),請(qǐng)聯(lián)系本人進(jìn)行刪除。

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

1.1 單一職責(zé)原則

單一職責(zé)原則規(guī)定一個(gè)類應(yīng)該有且僅有一個(gè)引起它變化的原因,否則類應(yīng)該被拆分。通俗的講:一個(gè)類只負(fù)責(zé)一個(gè)職責(zé),從業(yè)務(wù)層面來講就是在不同的業(yè)務(wù)層級(jí)上,一個(gè)類或方法只負(fù)責(zé)一個(gè)事情。

1.2 開閉原則

軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。可以通過“抽象約束、封裝變化”來實(shí)現(xiàn)開閉原則,即通過接口或者抽象類為軟件實(shí)體定義一個(gè)相對(duì)穩(wěn)定的抽象層,而將相同的可變因素封裝在相同的具體實(shí)現(xiàn)類中。

1.3 里氏替換原則

繼承必須確保超類所擁有的性質(zhì)在子類中仍然成立。即:子類可以擴(kuò)展父類的功能,但不能改變父類原有的功能。也就是說:子類繼承父類時(shí),除添加新的方法完成新增功能外,盡量不要重寫父類的方法。詳細(xì)解釋:

  • 子類可以實(shí)現(xiàn)父類的抽象方法,但不能覆蓋父類的非抽象方法
  • 子類中可以增加自己特有的方法
  • 當(dāng)子類的方法重載父類的方法時(shí),方法的前置條件(即方法的輸入?yún)?shù))要比父類的方法更寬松
  • 當(dāng)子類的方法實(shí)現(xiàn)父類的方法時(shí)(重寫/重載或?qū)崿F(xiàn)抽象方法),方法的后置條件(即方法的的輸出/返回值)要比父類的方法更嚴(yán)格或相等

1.4 依賴倒置原則

高層模塊不應(yīng)該依賴低層模塊,兩者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴抽象。其核心思想是:要面向接口編程,不要面向?qū)崿F(xiàn)編程。
依賴倒置原則的實(shí)現(xiàn)方法:

  • 每個(gè)類盡量提供接口或抽象類,或者兩者都具備。
  • 變量的聲明類型盡量是接口或者是抽象類。
  • 任何類都不應(yīng)該從具體類派生。
  • 使用繼承時(shí)盡量遵循里氏替換原則。

1.5 接口隔離原則

應(yīng)盡量將臃腫龐大的接口拆分成更小的和更具體的接口,讓接口中只包含使用者感興趣的方法。也就是說,要為各個(gè)類建立它們需要的專用接口,而不要試圖去建立一個(gè)很龐大的接口供所有依賴它的類去調(diào)用。

  • 接口隔離原則和單一職責(zé)都是為了提高類的內(nèi)聚性、降低它們之間的耦合性,體現(xiàn)了封裝的思想,但兩者是不同的:
  • 單一職責(zé)原則注重的是職責(zé),而接口隔離原則注重的是對(duì)接口依賴的隔離。
  • 單一職責(zé)原則主要是約束類,它針對(duì)的是程序中的實(shí)現(xiàn)和細(xì)節(jié);接口隔離原則主要約束接口,主要針對(duì)抽象和程序整體框架的構(gòu)建。

接口隔離原則的實(shí)現(xiàn)方法:

  • 接口盡量小,但是要有限度。一個(gè)接口只服務(wù)于一個(gè)子模塊或業(yè)務(wù)邏輯。
  • 為依賴接口的類定制服務(wù)。只提供調(diào)用者需要的方法,屏蔽不需要的方法。
  • 了解環(huán)境,拒絕盲從。每個(gè)項(xiàng)目或產(chǎn)品都有選定的環(huán)境因素,環(huán)境不同,接口拆分的標(biāo)準(zhǔn)就不同深入了解業(yè)務(wù)邏輯。
  • 提高內(nèi)聚,減少對(duì)外交互。使接口用最少的方法去完成最多的事情。

1.6 迪米特法則

迪米特法則又叫作最少知識(shí)原則。迪米特法則的定義是:只與你的直接朋友交談,不跟“陌生人”說話(Talk only to your immediate friends and not to strangers)。其含義是:如果兩個(gè)軟件實(shí)體無須直接通信,那么就不應(yīng)當(dāng)發(fā)生直接的相互調(diào)用,可以通過第三方轉(zhuǎn)發(fā)該調(diào)用。其目的是降低類之間的耦合度,提高模塊的相對(duì)獨(dú)立性。

迪米特法則的實(shí)現(xiàn)方法:

  • 從迪米特法則的定義和特點(diǎn)可知,它強(qiáng)調(diào)以下兩點(diǎn):
  • 從依賴者的角度來說,只依賴應(yīng)該依賴的對(duì)象。
  • 從被依賴者的角度說,只暴露應(yīng)該暴露的方法。

但是,過度使用迪米特法則會(huì)使系統(tǒng)產(chǎn)生大量的中介類,從而增加系統(tǒng)的復(fù)雜性,使模塊之間的通信效率降低。所以,在釆用迪米特法則時(shí)需要反復(fù)權(quán)衡,確保高內(nèi)聚和低耦合的同時(shí),保證系統(tǒng)的結(jié)構(gòu)清晰。

所以,在運(yùn)用迪米特法則時(shí)要注意以下 6 點(diǎn)。

  • 在類的劃分上,應(yīng)該創(chuàng)建弱耦合的類。類與類之間的耦合越弱,就越有利于實(shí)現(xiàn)可復(fù)用的目標(biāo)。
  • 在類的結(jié)構(gòu)設(shè)計(jì)上,盡量降低類成員的訪問權(quán)限。
  • 在類的設(shè)計(jì)上,優(yōu)先考慮將一個(gè)類設(shè)置成不變類。
  • 在對(duì)其他類的引用上,將引用其他對(duì)象的次數(shù)降到最低。
  • 不暴露類的屬性成員,而應(yīng)該提供相應(yīng)的訪問器(set 和 get 方法)。
  • 謹(jǐn)慎使用序列化(Serializable)功能。

1.7 合成復(fù)用原則

要求在軟件復(fù)用時(shí),要盡量先使用組合或者聚合等關(guān)聯(lián)關(guān)系來實(shí)現(xiàn),其次才考慮使用繼承關(guān)系來實(shí)現(xiàn)。

  • 如果要使用繼承關(guān)系,則必須嚴(yán)格遵循里氏替換原則。合成復(fù)用原則同里氏替換原則相輔相成的,兩者都是開閉原則的具體實(shí)現(xiàn)規(guī)范。
  • 實(shí)合成復(fù)用原則是通過將已有的對(duì)象納入新對(duì)象中,作為新對(duì)象的成員對(duì)象來實(shí)現(xiàn)的,新對(duì)象可以調(diào)用已有對(duì)象的功能,從而達(dá)到復(fù)用。

1.8 總結(jié)

以上7 種設(shè)計(jì)原則是軟件設(shè)計(jì)模式必須盡量遵循的原則,是設(shè)計(jì)模式的基礎(chǔ)。在實(shí)際開發(fā)過程中,并不是一定要求所有代碼都遵循設(shè)計(jì)原則,而是要綜合考慮人力、時(shí)間、成本、質(zhì)量,不刻意追求完美,要在適當(dāng)?shù)膱鼍白裱O(shè)計(jì)原則。這體現(xiàn)的是一種平衡取舍,可以幫助我們?cè)O(shè)計(jì)出更加優(yōu)雅的代碼結(jié)構(gòu)。

各種原則要求的側(cè)重點(diǎn)不同,下面我們分別用一句話歸納總結(jié)軟件設(shè)計(jì)模式的七大原則,如下表所示:

設(shè)計(jì)原則 一句話歸納 目的
開閉原則 對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉 降低維護(hù)帶來的新風(fēng)險(xiǎn)
依賴倒置原則 高層不應(yīng)該依賴低層,要面向接口編程 更利于代碼結(jié)構(gòu)的升級(jí)擴(kuò)展
單一職責(zé)原則 一個(gè)類只干一件事,實(shí)現(xiàn)類要單一 便于理解,提高代碼的可讀性
接口隔離原則 一個(gè)接口只干一件事,接口要精簡單一 功能解耦,高聚合、低耦合
迪米特法則 不該知道的不要知道,一個(gè)類應(yīng)該保持對(duì)其它對(duì)象最少的了解,降低耦合度 只和朋友交流,不和陌生人說話,減少代碼臃腫
里氏替換原則 不要破壞繼承體系,子類重寫方法功能發(fā)生改變,不應(yīng)該影響父類方法的含義 防止繼承泛濫
合成復(fù)用原則 盡量使用組合或者聚合關(guān)系實(shí)現(xiàn)代碼復(fù)用,少使用繼承 降低代碼耦合

參考鏈接

2 常見設(shè)計(jì)模式

由于設(shè)計(jì)模式共23種,內(nèi)容較多,本篇只對(duì)常見設(shè)計(jì)模式做簡單總結(jié)。先通過下表總結(jié):


image.png

image.png

2.1 單例模式

指一個(gè)類只有一個(gè)實(shí)例,且該類能自行創(chuàng)建這個(gè)實(shí)例的一種模式。例如,Windows 中只能打開一個(gè)任務(wù)管理器,這樣可以避免因打開多個(gè)任務(wù)管理器窗口而造成內(nèi)存資源的浪費(fèi),或出現(xiàn)各個(gè)窗口顯示內(nèi)容的不一致等錯(cuò)誤。

2.1.1 單例模式有 3 個(gè)特點(diǎn):

  • 單例類只有一個(gè)實(shí)例對(duì)象;
  • 該單例對(duì)象必須由單例類自行創(chuàng)建;
  • 單例類對(duì)外提供一個(gè)訪問該單例的全局訪問點(diǎn)。

優(yōu)點(diǎn):

  • 單例模式可以保證內(nèi)存里只有一個(gè)實(shí)例,減少了內(nèi)存的開銷。
  • 可以避免對(duì)資源的多重占用。
  • 單例模式設(shè)置全局訪問點(diǎn),可以優(yōu)化和共享資源的訪問。

缺點(diǎn):

  • 單例模式一般沒有接口,擴(kuò)展困難。如果要擴(kuò)展,則除了修改原來的代碼,沒有第二種途徑,違背開閉原則。
  • 在并發(fā)測(cè)試中,單例模式不利于代碼調(diào)試。在調(diào)試過程中,如果單例中的代碼沒有執(zhí)行完,也不能模擬生成一個(gè)新的對(duì)象。
  • 單例模式的功能代碼通常寫在一個(gè)類中,如果功能設(shè)計(jì)不合理,則很容易違背單一職責(zé)原則。

2.2 建造者模式

指將一個(gè)復(fù)雜對(duì)象的構(gòu)造與它的表示分離,使同樣的構(gòu)建過程可以創(chuàng)建不同的表示。它是將一個(gè)復(fù)雜的對(duì)象分解為多個(gè)簡單的對(duì)象,然后一步一步構(gòu)建而成。它將變與不變相分離,即產(chǎn)品的組成部分是不變的,但每一部分是可以靈活選擇的。

優(yōu)點(diǎn):

  1. 封裝性好,構(gòu)建和表示分離。
  2. 擴(kuò)展性好,各個(gè)具體的建造者相互獨(dú)立,有利于系統(tǒng)的解耦。
  3. 客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié),建造者可以對(duì)創(chuàng)建過程逐步細(xì)化,而不對(duì)其它模塊產(chǎn)生任何影響,便于控制細(xì)節(jié)風(fēng)險(xiǎn)。

缺點(diǎn):

  1. 產(chǎn)品的組成部分必須相同,這限制了其使用范圍。
  2. 如果產(chǎn)品的內(nèi)部變化復(fù)雜,如果產(chǎn)品內(nèi)部發(fā)生變化,則建造者也要同步修改,后期維護(hù)成本較大。

建造者(Builder)模式和工廠模式的關(guān)注點(diǎn)不同:建造者模式注重零部件的組裝過程,而工廠方法模式更注重零部件的創(chuàng)建過程,但兩者可以結(jié)合使用。

2.3 原型模式

  • 用一個(gè)已經(jīng)創(chuàng)建的實(shí)例作為原型,通過復(fù)制該原型對(duì)象來創(chuàng)建一個(gè)和原型相同或相似的新對(duì)象。重點(diǎn)在創(chuàng)建的是對(duì)象。即可以將原有對(duì)象的所有屬性值復(fù)制過來,保有了原對(duì)象的狀態(tài)。
  • 通過給原型類提供clone方法,將原有類對(duì)象的屬性深拷貝一份,生成新的對(duì)象實(shí)例。

2.4 工廠模式

定義一個(gè)創(chuàng)建產(chǎn)品對(duì)象的工廠接口,將產(chǎn)品對(duì)象的實(shí)際創(chuàng)建工作推遲到具體子工廠類當(dāng)中。這滿足創(chuàng)建型模式中所要求的“創(chuàng)建與使用相分離”的特點(diǎn)。作用主要是用來創(chuàng)建對(duì)象。

2.4.1 簡單工廠模式

簡單工廠模式每增加一個(gè)產(chǎn)品就要增加一個(gè)具體產(chǎn)品類和一個(gè)對(duì)應(yīng)的具體工廠類,這增加了系統(tǒng)的復(fù)雜度,違背了“開閉原則”。

    //抽象產(chǎn)品
    public interface Product {
        void show();
    }
    //具體產(chǎn)品:ProductA
    static class ConcreteProduct1 implements Product {
        public void show() {
            System.out.println("具體產(chǎn)品1顯示...");
        }
    }
    //具體產(chǎn)品:ProductB
    static class ConcreteProduct2 implements Product {
        public void show() {
            System.out.println("具體產(chǎn)品2顯示...");
        }
    }
    final class Const {
        static final int PRODUCT_A = 0;
        static final int PRODUCT_B = 1;
        static final int PRODUCT_C = 2;
    }
    static class SimpleFactory {
        public static Product makeProduct(int kind) {
            switch (kind) {
                case Const.PRODUCT_A:
                    return new ConcreteProduct1();
                case Const.PRODUCT_B:
                    return new ConcreteProduct2();
            }
            return null;
        }
    }

2.4.2 工廠方法模式

  • “工廠方法模式”是對(duì)簡單工廠模式的進(jìn)一步抽象化,其好處是可以使系統(tǒng)在不修改原來代碼的情況下引進(jìn)新的產(chǎn)品,即滿足開閉原則。
  • 將工廠類抽象出來,由具體的工廠類實(shí)現(xiàn)創(chuàng)建產(chǎn)品對(duì)象。

優(yōu)點(diǎn):

  • 用戶只需要知道具體工廠的名稱就可得到所要的產(chǎn)品,無須知道產(chǎn)品的具體創(chuàng)建過程。
  • 靈活性增強(qiáng),對(duì)于新產(chǎn)品的創(chuàng)建,只需多寫一個(gè)相應(yīng)的工廠類。
  • 典型的解耦框架。高層模塊只需要知道產(chǎn)品的抽象類,無須關(guān)心其他實(shí)現(xiàn)類,滿足迪米特法則、依賴倒置原則和里氏替換原則。

缺點(diǎn):

  • 類的個(gè)數(shù)容易過多,增加復(fù)雜度
  • 增加了系統(tǒng)的抽象性和理解難度
  • 抽象產(chǎn)品只能生產(chǎn)一種產(chǎn)品,此弊端可使用抽象工廠模式解決。

應(yīng)用場景:

  • 客戶只知道創(chuàng)建產(chǎn)品的工廠名,而不知道具體的產(chǎn)品名。如 TCL 電視工廠、海信電視工廠等。
  • 創(chuàng)建對(duì)象的任務(wù)由多個(gè)具體子工廠中的某一個(gè)完成,而抽象工廠只提供創(chuàng)建產(chǎn)品的接口。
  • 客戶不關(guān)心創(chuàng)建產(chǎn)品的細(xì)節(jié),只關(guān)心產(chǎn)品的品牌

模式的結(jié)構(gòu)與實(shí)現(xiàn)

工廠方法模式由抽象工廠、具體工廠、抽象產(chǎn)品和具體產(chǎn)品等4個(gè)要素構(gòu)成。本節(jié)來分析其基本結(jié)構(gòu)和實(shí)現(xiàn)方法。

模式的結(jié)構(gòu)

工廠方法模式的主要角色如下:

  1. 抽象工廠(Abstract Factory):提供了創(chuàng)建產(chǎn)品的接口,調(diào)用者通過它訪問具體工廠的工廠方法 newProduct() 來創(chuàng)建產(chǎn)品。
  2. 具體工廠(ConcreteFactory):主要是實(shí)現(xiàn)抽象工廠中的抽象方法,完成具體產(chǎn)品的創(chuàng)建。
  3. 抽象產(chǎn)品(Product):定義了產(chǎn)品的規(guī)范,描述了產(chǎn)品的主要特性和功能。
  4. 具體產(chǎn)品(ConcreteProduct):實(shí)現(xiàn)了抽象產(chǎn)品角色所定義的接口,由具體工廠來創(chuàng)建,它同具體工廠之間一一對(duì)應(yīng)。

2.4.3 抽象工廠模式

是對(duì)工廠方法模式的升級(jí),抽象工廠類負(fù)責(zé)生成一系列相關(guān)產(chǎn)品的創(chuàng)建,而不只是生成同等級(jí)的不同產(chǎn)品類。即生成的是相關(guān)聯(lián)的不同等級(jí)的產(chǎn)品類。

抽象工廠模式通常適用于以下場景:

  • 當(dāng)需要?jiǎng)?chuàng)建的對(duì)象是一系列相互關(guān)聯(lián)或相互依賴的產(chǎn)品族時(shí),如電器工廠中的電視機(jī)、洗衣機(jī)、空調(diào)等。
  • 系統(tǒng)中有多個(gè)產(chǎn)品族,但每次只使用其中的某一族產(chǎn)品。如有人只喜歡穿某一個(gè)品牌的衣服和鞋。
  • 系統(tǒng)中提供了產(chǎn)品的類庫,且所有產(chǎn)品的接口相同,客戶端不依賴產(chǎn)品實(shí)例的創(chuàng)建細(xì)節(jié)和內(nèi)部結(jié)構(gòu)。

優(yōu)點(diǎn):

  • 可以在類的內(nèi)部對(duì)產(chǎn)品族中相關(guān)聯(lián)的多等級(jí)產(chǎn)品共同管理,而不必專門引入多個(gè)新的類來進(jìn)行管理。
  • 當(dāng)需要產(chǎn)品族時(shí),抽象工廠可以保證客戶端始終只使用同一個(gè)產(chǎn)品的產(chǎn)品組。
  • 抽象工廠增強(qiáng)了程序的可擴(kuò)展性,當(dāng)增加一個(gè)新的產(chǎn)品族時(shí),不需要修改原代碼,滿足開閉原則。

缺點(diǎn):

  • 當(dāng)產(chǎn)品族中需要增加一個(gè)新的產(chǎn)品時(shí),所有的工廠類都需要進(jìn)行修改。增加了系統(tǒng)的抽象性和理解難度。

2.5 代理模式

由于某些原因需要給某對(duì)象提供一個(gè)代理以控制對(duì)該對(duì)象的訪問。這時(shí),訪問對(duì)象不適合或者不能直接引用目標(biāo)對(duì)象,代理對(duì)象作為訪問對(duì)象和目標(biāo)對(duì)象之間的中介。

優(yōu)點(diǎn):

  • 代理模式在客戶端與目標(biāo)對(duì)象之間起到一個(gè)中介作用和保護(hù)目標(biāo)對(duì)象的作用;
  • 代理對(duì)象可以擴(kuò)展目標(biāo)對(duì)象的功能;即在真是調(diào)用某個(gè)方法的前后插入預(yù)處理方法和收尾方法
  • 代理模式能將客戶端與目標(biāo)對(duì)象分離,在一定程度上降低了系統(tǒng)的耦合度,增加了程序的可擴(kuò)展性

缺點(diǎn):

  • 代理模式會(huì)造成系統(tǒng)設(shè)計(jì)中類的數(shù)量增加
  • 在客戶端和目標(biāo)對(duì)象之間增加一個(gè)代理對(duì)象,會(huì)造成請(qǐng)求處理速度變慢;
  • 增加了系統(tǒng)的復(fù)雜度;
    那么如何解決以上提到的缺點(diǎn)呢?答案是可以使用動(dòng)態(tài)代理方式

2.5.1 分類:

根據(jù)代理的創(chuàng)建時(shí)期,代理模式分為靜態(tài)代理和動(dòng)態(tài)代理。

  • 靜態(tài):由程序員創(chuàng)建代理類或特定工具自動(dòng)生成源代碼再對(duì)其編譯,在程序運(yùn)行前代理類的 .class 文件就已經(jīng)存在了。
  • 動(dòng)態(tài):在程序運(yùn)行時(shí),運(yùn)用反射機(jī)制動(dòng)態(tài)創(chuàng)建而成。

樣例:

package proxy;
public class ProxyTest {
    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.Request();
    }
}
//抽象主題
interface Subject {
    void Request();
}
//真實(shí)主題
class RealSubject implements Subject {
    public void Request() {
        System.out.println("訪問真實(shí)主題方法...");
    }
}
//代理
class Proxy implements Subject {
    private RealSubject realSubject;
    public void Request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        preRequest();
        realSubject.Request();
        postRequest();
    }
    public void preRequest() {
        System.out.println("訪問真實(shí)主題之前的預(yù)處理。");
    }
    public void postRequest() {
        System.out.println("訪問真實(shí)主題之后的后續(xù)處理。");
    }
}

2.5.2 動(dòng)態(tài)代理

也叫接口代理,通過反射實(shí)現(xiàn)。能在代碼運(yùn)行時(shí)動(dòng)態(tài)地改變某個(gè)對(duì)象的代理,并且能為代理對(duì)象動(dòng)態(tài)地增加方法、增加行為。
實(shí)現(xiàn)方式:

  • 通過Java反射機(jī)制,獲取被代理類的實(shí)例。即在書寫代碼時(shí),不需要知道具體的被代理類是誰。
  • 被代理類要實(shí)現(xiàn)被代理的方法。即實(shí)現(xiàn)以下示例的IPerson接口的 findTeacher() 。

樣例:

  • 代理類:
public class JdkFuDao implements InvocationHandler {
    private IPerson target;
    public IPerson getInstance(IPerson target) {
        this.target = target;
        Class<?> clazz = target.getClass();
        return (IPerson) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(this.target, args);
        after();
        return result;
    }
    private void after() {
        System.out.println("雙方同意,開始輔導(dǎo)");
    }
    private void before() {
        System.out.println("這里是C語言中文網(wǎng)輔導(dǎo)班,已經(jīng)收集到您的需求,開始挑選老師");
    }
}
  • 被代理類:趙六(實(shí)現(xiàn)IPerson )
public class ZhaoLiu implements IPerson {
    @Override
    public void findTeacher() {
        System.out.println("符合趙六的要求");
    }
    public void buyInsure() {
    }
}
  • 代理接口:
public interface IPerson {
    void findTeacher(); //找老師
}
  • 執(zhí)行:
public class Test {
    public static void main(String[] args) {
        JdkFuDao jdkFuDao = new JdkFuDao();
        IPerson zhaoliu = jdkFuDao.getInstance(new ZhaoLiu());
        zhaoliu.findTeacher();
    }
}

2.6 適配器模式

將一個(gè)類的接口轉(zhuǎn)換成客戶端希望的另外一個(gè)接口,使得原本由于接口不兼容而不能一起工作的那些類能一起工作。適配器類實(shí)現(xiàn)目標(biāo)類的接口,并繼承被適配類,達(dá)到在在適配器類中調(diào)用目標(biāo)類的目的。

2.7 裝飾器模式

將原有對(duì)象傳進(jìn)來并調(diào)用原有對(duì)象的方法,同時(shí)在新類中拓展其他方法,開發(fā)中很常用。

2.8 外觀模式

將多個(gè)對(duì)象的多個(gè)方法封裝到一個(gè)方法中進(jìn)行調(diào)用。提供給外部調(diào)用類的方法只有一個(gè)。即隱藏了實(shí)現(xiàn),用戶不需要關(guān)心具體的實(shí)現(xiàn)。

2.9 組合模式

如Collection(接口)集合,子集合List、Set等。定義了Collection的方法,不同的子類去實(shí)現(xiàn)Collection接口的方法。

2.10 模板方法模式

定義一個(gè)操作中的算法骨架,而將算法的一些步驟延遲到子類中,使得子類可以不改變?cè)撍惴ńY(jié)構(gòu)的情況下重定義該算法的某些特定步驟。它是一種類行為型模式。經(jīng)典的有Android中的Activity回調(diào)方法。

2.11 策略模式

該模式定義了一系列算法,并將每個(gè)算法封裝起來,使它們可以相互替換,且算法的變化不會(huì)影響使用算法的客戶。
實(shí)現(xiàn)方式:

  • 抽象策略(Strategy)類:定義了一個(gè)公共接口,各種不同的算法以不同的方式實(shí)現(xiàn)這個(gè)接口。
  • 具體策略(Concrete Strategy)類:實(shí)現(xiàn)了抽象策略定義的接口,提供具體的算法實(shí)現(xiàn)。
  • 環(huán)境(Context)類:持有一個(gè)策略類的引用,最終給客戶端調(diào)用。即環(huán)境類通過傳入不同的策略對(duì)象,實(shí)現(xiàn)不同的算法。跟if-else思路相同,只是將實(shí)現(xiàn)封裝到策略類里,if-else放到環(huán)境類里做判斷(實(shí)例化不同的策略類)

2.12 責(zé)任鏈模式

為了避免請(qǐng)求發(fā)送者與多個(gè)請(qǐng)求處理者耦合在一起,于是將所有請(qǐng)求的處理者通過前一對(duì)象記住其下一個(gè)對(duì)象的引用而連成一條鏈;當(dāng)有請(qǐng)求發(fā)生時(shí),可將請(qǐng)求沿著這條鏈傳遞,直到有對(duì)象處理它為止。經(jīng)典的有Android中的View事件處理機(jī)制,事件是否向下傳遞,用當(dāng)前對(duì)象是否需要處理掉,需要?jiǎng)t自己消費(fèi),不消費(fèi),向下傳遞。

2.13 觀察者模式

指多個(gè)對(duì)象間存在一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新。
實(shí)現(xiàn)方式:
被觀察著保存觀察者對(duì)象的集合(訂閱),當(dāng)被觀察者狀態(tài)發(fā)生改變時(shí),通過調(diào)用觀察者的回調(diào)方法(發(fā)布)去通知觀察者執(zhí)行更新操作。具體如下:

  • 抽象主題(Subject)角色:也叫抽象目標(biāo)類,它提供了一個(gè)用于保存觀察者對(duì)象的聚集類和增加、刪除觀察者對(duì)象的方法,以及通知所有觀察者的抽象方法。
  • 具體主題(Concrete Subject)角色:也叫具體目標(biāo)類,它實(shí)現(xiàn)抽象目標(biāo)中的通知方法,當(dāng)具體主題的內(nèi)部狀態(tài)發(fā)生改變時(shí),通知所有注冊(cè)過的觀察者對(duì)象。
  • 抽象觀察者(Observer)角色:它是一個(gè)抽象類或接口,它包含了一個(gè)更新自己的抽象方法,當(dāng)接到具體主題的更改通知時(shí)被調(diào)用。
  • 具體觀察者(Concrete Observer)角色:實(shí)現(xiàn)抽象觀察者中定義的抽象方法,以便在得到目標(biāo)的更改通知時(shí)更新自身的狀態(tài)。

2.14 備忘錄模式

在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài),以便以后當(dāng)需要時(shí)能將該對(duì)象恢復(fù)到原先保存的狀態(tài)。該模式又叫快照模式。
實(shí)現(xiàn)方式:提供一個(gè)保存某個(gè)對(duì)象管理類和發(fā)起人,用來發(fā)起和管理需要保存狀態(tài)的對(duì)象。

  • 管理類:保存對(duì)象的類
  • 發(fā)起人:拷貝對(duì)象,并把對(duì)象set到管理類中,提供存取方法

2.15 享元模式

運(yùn)用共享技術(shù)來有效地支持大量細(xì)粒度對(duì)象的復(fù)用。它通過共享已經(jīng)存在的對(duì)象來大幅度減少需要?jiǎng)?chuàng)建的對(duì)象數(shù)量、避免大量相似類的開銷,從而提高系統(tǒng)資源的利用率。

參考鏈接

最后編輯于
?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 1.說一下設(shè)計(jì)模式?你都知道哪些? 答:設(shè)計(jì)模式總共有 23 種,總體來說可以分為三大類:創(chuàng)建型模式( Creat...
    you的日常閱讀 8,569評(píng)論 1 3
  • 背景 最近在準(zhǔn)備面試,結(jié)合之前的工作經(jīng)驗(yàn)和近期在網(wǎng)上收集的一些面試資料,準(zhǔn)備將Android開發(fā)崗位的知識(shí)點(diǎn)做一個(gè)...
    陳祥_閱讀 1,454評(píng)論 2 11
  • 背景 最近在準(zhǔn)備面試,結(jié)合之前的工作經(jīng)驗(yàn)和近期在網(wǎng)上收集的一些面試資料,準(zhǔn)備將Android開發(fā)崗位的知識(shí)點(diǎn)做一個(gè)...
    陳祥_閱讀 3,200評(píng)論 4 33
  • 背景 最近在準(zhǔn)備面試,結(jié)合之前的工作經(jīng)驗(yàn)和近期在網(wǎng)上收集的一些面試資料,準(zhǔn)備將Android開發(fā)崗位的知識(shí)點(diǎn)做一個(gè)...
    陳祥_閱讀 2,474評(píng)論 0 10
  • 背景 最近在準(zhǔn)備面試,結(jié)合之前的工作經(jīng)驗(yàn)和近期在網(wǎng)上收集的一些面試資料,準(zhǔn)備將Android開發(fā)崗位的知識(shí)點(diǎn)做一個(gè)...
    陳祥_閱讀 1,243評(píng)論 0 3

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