設(shè)計模式

2020-04-21 09:55 更新

筆者能力有限,總結(jié)有誤的地方,請讀者協(xié)作更正。需要了解更多,請閱讀相關(guān)書籍。

能說出來解釋清楚,最好能寫出偽代碼

23種設(shè)計模式分3類:創(chuàng)建型5種,結(jié)構(gòu)型分7種,行為型11種

設(shè)計模式的6大原則:

  • 總原則:開閉原則,對擴(kuò)展開放,對修改關(guān)閉

  • 單一職責(zé),里氏替換,依賴倒轉(zhuǎn),接口隔離,最少知道,合成復(fù)用

1.單例模式8種

基本實(shí)現(xiàn)思路:保證JVM中只能創(chuàng)建一個該對象的實(shí)例。對頻繁創(chuàng)建和銷毀對象時使用;工具類使用;

實(shí)現(xiàn)步驟:

?私有靜態(tài)變量;私有構(gòu)造方法;

?靜態(tài)方法,調(diào)用該方法,持有對象引用,返回該引用;引用為空,創(chuàng)建實(shí)例。

1)餓漢模式(靜態(tài)常量)可用

    public class Singleton {
        private final static Singleton INSTANCE = new Singleton();
        private Singleton(){}
        public static Singleton getInstance(){
            return INSTANCE;
        }

優(yōu)點(diǎn):避免線程同步

缺點(diǎn):類加載之后,對象就創(chuàng)建出來在哪里放著,不管用不用,沒有懶加載效果,內(nèi)存浪費(fèi)。

2)餓漢式(靜態(tài)代碼塊)可用

把對象的創(chuàng)建放在靜態(tài)代碼塊中,優(yōu)缺點(diǎn)和上面一樣。

public class Singleton {
    private static Singleton instance;
    static {
        instance = new Singleton();
    }
    private Singleton() {}
    public class Singleton {
        private static Singleton instance;
        static {
            instance = new Singleton();
        }
        private Singleton() {}

3)懶漢模式(線程不安全)不可用

把對象的創(chuàng)建放在方法中,需要用的時候在創(chuàng)建;能實(shí)現(xiàn)懶加載,存在線程不安全。

    public class Singleton {
        private static Singleton singleton;
        private Singleton() {}
        public static Singleton getInstance() {
            if (singleton == null) {
                singleton = new Singleton();
            }
            return singleton;
        }

4)懶漢模式(線程安全,同步方法)可用,不推薦

加鎖,懶加載,線程安全,但是效率低

   public class Singleton {
        private static Singleton singleton;
        private Singleton() {}
        public static synchronized Singleton getInstance() {
            if (singleton == null) {
                singleton = new Singleton();
            }
            return singleton;
        }

5)懶漢模式(線程安全,同步代碼塊)不可用

    public class Singleton {
        private static Singleton singleton;
        private Singleton() {}
        public static Singleton getInstance() {
            if (singleton == null) {
                synchronized (Singleton.class) {
                    singleton = new Singleton();
                }
            }

線程安全,但是會產(chǎn)生多個實(shí)例;

6)雙重檢查(推薦用)

    public class Singleton {
        private static volatile Singleton singleton;
        private Singleton() {}
        public static Singleton getInstance() {
            if (singleton == null) {
                synchronized (Singleton.class) {
                    if (singleton == null) {
                        singleton = new Singleton();
                    } } }
            return singleton;
        }
    }

進(jìn)行了兩次if (singleton == null)檢查,這樣就可以保證線程安全了。這樣,實(shí)例化代碼只用執(zhí)行一次,后面再次訪問時,判斷if (singleton == null),直接return實(shí)例化對象。

優(yōu)點(diǎn):線程安全;延遲加載;效率較高。

7)靜態(tài)內(nèi)部類(推薦用)

    public class Singleton 
        private Singleton() {}
        private static class SingletonInstance {
            private static final Singleton INSTANCE = new Singleton();
        }
        public static Singleton getInstance() {
            return SingletonInstance.INSTANCE;
        }
    }

類的靜態(tài)屬性只會在第一次加載類的時候進(jìn)行初始化,JVM能夠幫我們保證線程安全,在進(jìn)行初始化的時候,別的線程無法進(jìn)入。

優(yōu)點(diǎn):線程安全,延遲加載,效率高。

8)枚舉(推薦用)

     public enum Singleton{
    Instance;
    private void  EvenMethod(){
        }
    }

JDK1.5中添加的枚舉來實(shí)現(xiàn)單例模式。

不僅能避免多線程同步問題,而且還能防止反序列化重新創(chuàng)建新的對象。

2.工廠方法

簡單工廠方法

不同的類實(shí)現(xiàn)同一個接口,創(chuàng)建一個簡單工廠來為這些類創(chuàng)建實(shí)例;

例如:發(fā)送短信,發(fā)送郵件,將發(fā)送抽取出來作為接口,建一個簡單工廠來實(shí)現(xiàn)發(fā)送的實(shí)例,當(dāng)然還有其它的寫法。

工廠方法

簡單工廠存在的問題,類的創(chuàng)建依賴于工廠類,想要修改程序就需要修改工廠,違背了閉包原則

工廠方法,擴(kuò)展功能,直接增加工廠類。

3.抽象工廠

工廠方法中,一個工廠只能生產(chǎn)一種產(chǎn)品。重點(diǎn)在于產(chǎn)品,如果一個方法需要有大量的實(shí)現(xiàn)細(xì)節(jié),很多代碼需要圍繞這個產(chǎn)品展開,推薦使用工廠方法。

抽象工廠中,一個工廠可以創(chuàng)建多種產(chǎn)品類,因?yàn)槌橄蠊S中有一堆的工廠方法,一個工廠方法返回對應(yīng)的數(shù)據(jù)類型。重點(diǎn)在于數(shù)量,如果要求不同的產(chǎn)品線,保持接口一致,推薦使用抽象工廠方法。

4.代理模式

1)就是用另外一個類代替目標(biāo)類的操作,同時能夠提供額外的操作;

比如:房地產(chǎn)中介,客戶,和房東就是一個代理模式;

  • -地產(chǎn)中介 賣房,帶客戶看房,收取中介費(fèi)
  • -房東 賣房
  • -客戶 買房

2)分類:靜態(tài)代理,和動態(tài)代理 spring中AOP應(yīng)用了兩種代理模式,ciglib動態(tài)代理,jdk動態(tài)代理 詳解Spring的AOP?

1.1 靜態(tài)代理

特點(diǎn):實(shí)現(xiàn)和被代理這相同的接口,能夠執(zhí)行代理者相同的方法,添加額外的功能操作

缺點(diǎn):一個目標(biāo)對象就需要一個代理類,一個明星就需要一個經(jīng)濟(jì)人

復(fù)用性不高,不通用

1.2 動態(tài)代理

分為-->JDK代理 CGlib代理 -jdk動態(tài)代理

特點(diǎn):實(shí)現(xiàn)相同的接口,執(zhí)行目標(biāo)對象的方法,能做額外的操作,

優(yōu)點(diǎn):一個代理類,能為很多目標(biāo)類服務(wù),解耦,高復(fù)用

缺點(diǎn):只能處理事務(wù),不具備通用性(日志,安全,權(quán)限等)

-CGlib動態(tài)代理

特點(diǎn):執(zhí)行目標(biāo)對象的方法,能做額外的操作

優(yōu)點(diǎn):一個代理類,能為很多目標(biāo)類服務(wù),解耦,高復(fù)用,而且不需要實(shí)現(xiàn)接口,

1.3 Spring 生成代理對象

Spring整合了JDK代理和Cglib代理,

Jdk代理實(shí)現(xiàn)的是invocationHandler接口;Cglib實(shí)現(xiàn)的是MethodInterceptor接口

實(shí)現(xiàn)著兩個接口,spring代理模式內(nèi)部能夠的自由切換。讓代理模式復(fù)用性更高,使用更方便。

5.裝飾器模式

裝飾模式和代理模式很像,都是為了擴(kuò)展功能,

裝飾模式要求給一個對象動態(tài)的增加一些新的功能,要求裝飾對象和被裝飾對象實(shí)現(xiàn)共同的接口,裝飾對象持有被裝飾對象的引用。

6.策略模式

就是定義一系列的算法族,將每一個算法封裝成獨(dú)立的類,然后所有的類實(shí)現(xiàn)統(tǒng)一的接口,這些算法之間可以相互替換,每一個算法的變化不會影響到用戶的使用。

需要設(shè)計一個接口,為一序列類提供統(tǒng)一的方法,多個實(shí)現(xiàn)類實(shí)現(xiàn)該接口,設(shè)計一個抽象類,提供輔助函數(shù)。

7.觀察者模式

是一種一隊(duì)多的關(guān)系,就像公眾號和粉絲的關(guān)系;

當(dāng)一個對象發(fā)生變化時候,其它依賴于該對象的類都會收到通知;

8.責(zé)任鏈模式

就是,有多個對象,每一個對象持有下一個對象的引用,形成一條鏈,請求在這條鏈上傳遞,直到被某一對象被處理,但是請求并不知道是哪一個對象處理了這個請求。

比喻:我去拜訪元首,第一道安檢,讓我初始通行證;第二道安全,搜身;第三道安檢,是否預(yù)約;每一次安檢負(fù)責(zé)每一次安檢的工作,所有的安檢形成一條鏈,我作為一個對象在這條鏈上傳遞,安檢不通過,拋異常。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號