最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java設(shè)計模式之創(chuàng)建者模式詳解

 更新時間:2023年08月18日 08:30:46   作者:劉婉晴  
這篇文章主要介紹了Java設(shè)計模式之創(chuàng)建者模式詳解,創(chuàng)建者模式,顧名思義,就是提供友好的創(chuàng)建對象的方式?,對象都是?new?出來的,但是在一些情況下,這種方式不是很友好,首先,它不夠直觀,需要的朋友可以參考下

前言

創(chuàng)建者模式,顧名思義,就是提供友好的創(chuàng)建對象的方式 ,對象都是 new 出來的,但是在一些情況下,這種方式不是很友好

首先,它不夠直觀,其次,在一些情況下,這樣創(chuàng)建的對象不滿足要求。

比如 : 當我們需要創(chuàng)建單例的對象,那我們就不能每次用的時候就重新 new, 這樣很明顯是不合理的 。

一、工廠模式

引入工廠類的原因 : 是因為我們需要兩個或者兩個以上的工廠生產(chǎn)對象,假如我們就需要一個對象的工廠,那就沒必要引入工廠類了 。

1. 簡單工廠模式

就一個工廠,它具有不同的方法,生產(chǎn)出不同的產(chǎn)品 。

在這里插入圖片描述

2. 工廠模式

我們需要兩個及以上的工廠,所以抽象出一個工廠接口,其他工廠實現(xiàn)類實現(xiàn)這個抽象接口,重寫創(chuàng)建方法 。

在這里插入圖片描述

3. 抽象工廠模式

涉及到產(chǎn)品族問題 , 調(diào)用的時候先選擇工廠,再調(diào)用其方法,生成相應(yīng)的產(chǎn)品。

在這里插入圖片描述

工廠模式在 Spring 框架中的使用

Spring 框架通過反射機制實現(xiàn)工廠模式,從而降低了程序的耦合程度 。

具體實現(xiàn)思路為 : 讀取配置文件中相關(guān)值, 然后通過反射 Class.forName 得到該值對應(yīng)的類,再通過 newInstance() 獲取該類的實例返回 。

我們調(diào)用時只需要 : Factory.getXXX("我們定義在配置文件中的 Bean 名稱")

二、單例模式

1. 餓漢式實現(xiàn)

私有構(gòu)造方法 + 創(chuàng)建靜態(tài)實例

public class Singleton {
    // 私有構(gòu)造方法
    private Singleton() {};
    // 創(chuàng)建私有靜態(tài)實例
    private static Singleton instance = new Singleton();
    public static Singleton getInstance() {
        return instance;
    }
}

缺點 : 不想用 Singleton 實例時,它也生成了,因為是 static 的, 這個類被第一次使用時就會被生成 。

2. 飽漢式實現(xiàn) 雙重檢查機制原理

私有構(gòu)造方法 + volatile 修飾 + 雙重判空,加鎖

public class Singleton {
    // 私有構(gòu)造方法
    private Singleton() {}
    // valitale 修飾
    private static volatile Singleton instance = null;
    public static Singleton getInstance() {
    	// 雙重檢查是否為 null
        if (instance == null) {
            // 加鎖
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

為什么要在實例化時加 synchronized 鎖, 不是已經(jīng)用 volatile 關(guān)鍵字修飾了嗎 ?

因為 volatile 只可以保證變量的可見性 和 防止實例化時指令重排 ,它不能保證操作的原子性 。我們要求只能有一個線程去實例化,不能一堆線程一起進去實例化 。

不是已經(jīng)有 synchronized 鎖了嗎,為什么還要 volatile 關(guān)鍵字修飾 ?

因為我們得保證 一個線程實例化 Singleton 后,其他線程可見,直接返回就行,所以我們需要 volatile 去保證 Singleton 在多個線程中的可見性 , 不被 JVM 緩存。

除此之外,它也通過防止對象創(chuàng)建時的指令重排,而使得線程安全 。

什么是指令重排 ? 創(chuàng)建對象時,先分配內(nèi)存空間,然后實例指向該空間地址,然后才初始化 。

正常情況應(yīng)該是, 分配內(nèi)存空間 — 初始化 — 指向該空間地址

如果不用 volatile 修飾, 發(fā)生指令重排時, 創(chuàng)建對象的線程只是指向了空間地址,但是還沒初始化,但是因為已經(jīng)指向地址了

下一個線程在第一重 null 檢查時,判斷為非 null,直接返回了,但是返回的實例還沒初始化 。這是線程不安全的,所以需要 volatile 。

3. 嵌套類實現(xiàn)

利用嵌套類可以 訪問外部類 的屬性和方法 。在嵌套類中實例化 Singleton 。

public class Singleton {
    private Singleton() {}
    // 利用嵌套類可以訪問外部類的屬性和方法
    private static class Holder {
        private static Singleton instance = new Singleton();
    }
    public static Singleton getInstance() {
        return Holder.instance;
    }
}

4. 枚舉實現(xiàn) *

public enum Singleton {
     INSTANCE;
}

據(jù)說被谷歌大佬作為實現(xiàn)單例的最佳實踐 —— 即簡單又安全

下面我們來一起簡單看一下枚舉為什么可以實現(xiàn)單例 ?

我們自定義的枚舉類 默認 繼承 Enum, Enum 的源碼如下 :

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
    // 枚舉項的名字 , 程序員用 toString 方法而不是這個
    private final String name;
    public final String name() {
        return name;
    }
	// 程序員用不到的,給使用枚舉類型的 API 使用,比如  java.util.EnumSet
    private final int ordinal;
    public final int ordinal() {
        return ordinal;
    }
	// 程序員用不到的,給編譯器發(fā)出的代碼,告訴編譯器實例化這個枚舉類
    protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }
    public String toString() {
        return name;
    }
    public final boolean equals(Object other) {
        return this==other;
    }
    public final int hashCode() {
        return super.hashCode();
    }
	// 克隆枚舉類拋出異常,這保證了枚舉永遠不會被克隆,這對于保持它們的 "單例 "狀態(tài)是必要的。
    protected final Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }
    public final int compareTo(E o) {
        Enum<?> other = (Enum<?>)o;
        Enum<E> self = this;
        if (self.getClass() != other.getClass() && // optimization
            self.getDeclaringClass() != other.getDeclaringClass())
            throw new ClassCastException();
        return self.ordinal - other.ordinal;
    }
    @SuppressWarnings("unchecked")
    public final Class<E> getDeclaringClass() {
        Class<?> clazz = getClass();
        Class<?> zuper = clazz.getSuperclass();
        return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
    }
	// 返回這個枚舉常量的枚舉類型所對應(yīng)的Class對象
    public static <T extends Enum<T>> T valueOf(Class<T> enumType,
                                                String name) {
        T result = enumType.enumConstantDirectory().get(name);
        if (result != null)
            return result;
        if (name == null)
            throw new NullPointerException("Name is null");
        throw new IllegalArgumentException(
            "No enum constant " + enumType.getCanonicalName() + "." + name);
    }
    protected final void finalize() { }
    private void readObject(ObjectInputStream in) throws IOException,
        ClassNotFoundException {
        throw new InvalidObjectException("can't deserialize enum");
    }
    private void readObjectNoData() throws ObjectStreamException {
        throw new InvalidObjectException("can't deserialize enum");
    }
}

我們定義的枚舉類里面的每個枚舉項都是一個 Enum, 這個 Enum 都是 static final 類型的,也就是說不容許被修改,初次之外我們的自定義的枚舉類默認私有構(gòu)造方法(體現(xiàn)在編譯完之后),不能被程序員改成 public 的

我們再翻譯一下,翻譯成我覺得更好理解的

首先, 枚舉類里的枚舉項都是 枚舉類 Enum 的實例,枚舉幫我們自動處理了一些東西,簡化了代碼其幫我們進行的操作就是對每個枚舉項私有了構(gòu)造方法,然后實例定義成 static final 類型的,就是相當于我們餓漢式的實現(xiàn)代碼,其幫我們封裝好了,就是其幫我們封裝好了餓漢式的實現(xiàn)代碼除此之外,我們枚舉類的實例只能有我們在枚舉類里的那幾個,對單例來說只有那一個,不容許再進行擴張實例 ,只能有那一個。

三、建造者模式

鏈式調(diào)用方法,實現(xiàn)對象的創(chuàng)建 。為什么優(yōu)于 new ?

首先,一個設(shè)計模式是最佳實踐是相對其使用場景說的。

建造者模式適用于要創(chuàng)建的對象非常復(fù)雜的情況,構(gòu)造者模式讓這個復(fù)雜類的裝配變得按部就班又直觀。

舉個栗子

MyBatis 中讀取配置文件構(gòu)建配置類,這個配置類超級大 。所以使用了建造者模式,把這個復(fù)雜類的構(gòu)建拆分成了好多 builder,根據(jù)傳入的參數(shù)的不同進行創(chuàng)建 。

四、原型模式

對于原型模式,首先我們需要記住的就是實現(xiàn) Cloneable 接口,并且重寫 clone 方法 。(注意深淺克隆的區(qū)別)

其實,按照我對原型模式的理解,就是新建了一個模板。然后,我們不斷去克隆這個模版,更改模版中的一些值。

到此這篇關(guān)于Java設(shè)計模式之創(chuàng)建者模式詳解的文章就介紹到這了,更多相關(guān)Java創(chuàng)建者模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mybatis-spring:@MapperScan注解的使用

    mybatis-spring:@MapperScan注解的使用

    這篇文章主要介紹了mybatis-spring:@MapperScan注解的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java獲取request中的參數(shù)以及java解析URL問號后的參數(shù)

    java獲取request中的參數(shù)以及java解析URL問號后的參數(shù)

    這篇文章主要介紹了java獲取request中的參數(shù)以及java解析URL問號后的參數(shù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 如何使用Spring自定義Xml標簽

    如何使用Spring自定義Xml標簽

    要實現(xiàn)自定義的xml配置,需要有兩個默認spring配置文件來支持。一個是spring.schemas,一個是spring.handlers,前者是為了驗證你自定義的xml配置文件是否符合你的格式要求,后者是告訴spring該如何來解析你自定義的配置文件。本文將介紹如何使用Spring自定義Xml標簽
    2021-06-06
  • 詳解Eclipse提交項目到GitHub以及解決代碼沖突

    詳解Eclipse提交項目到GitHub以及解決代碼沖突

    這篇文章主要介紹了詳解Eclipse提交項目到GitHub以及解決代碼沖突,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • MyBatis+Calcite實現(xiàn)多數(shù)據(jù)庫SQL自動適配的詳細指南

    MyBatis+Calcite實現(xiàn)多數(shù)據(jù)庫SQL自動適配的詳細指南

    在當今企業(yè)IT環(huán)境中,數(shù)據(jù)庫異構(gòu)性已成為常態(tài),根據(jù)DB-Engines最新調(diào)研,超過78%的企業(yè)同時使用兩種以上數(shù)據(jù)庫系統(tǒng),所以本文就來為大家介紹一下如何基于MyBatis+Calcite實現(xiàn)多數(shù)據(jù)庫SQL自動適配吧
    2025-04-04
  • 使用Spring?AOP實現(xiàn)用戶操作日志功能

    使用Spring?AOP實現(xiàn)用戶操作日志功能

    這篇文章主要介紹了使用Spring?AOP實現(xiàn)了用戶操作日志功能,功能實現(xiàn)需要一張記錄日志的log表,結(jié)合示例代碼給大家講解的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • SpringBoot中Dozer的使用小結(jié)

    SpringBoot中Dozer的使用小結(jié)

    dozer是用來兩個對象之間屬性轉(zhuǎn)換的工具,有了這個工具之后,我們將一個對象的所有屬性值轉(zhuǎn)給另一個對象時,就不需要再去寫重復(fù)的set和get方法了,下面介紹下SpringBoot中Dozer的使用,感興趣的朋友一起看看吧
    2022-03-03
  • Springcloud中Feign傳遞參數(shù)的過程解析

    Springcloud中Feign傳遞參數(shù)的過程解析

    這篇文章主要介紹了Springcloud中Feign傳遞參數(shù)的過程,單個參數(shù)的傳值有兩種方式,第一種使用@RequestParam/@PathVariable進行傳值,傳遞多個參數(shù):多個參數(shù)的傳值可以使用多個@RequestParam來進行傳參,需要的朋友可以參考下
    2023-09-09
  • SpringBoot中EasyExcel實現(xiàn)Excel文件的導(dǎo)入導(dǎo)出

    SpringBoot中EasyExcel實現(xiàn)Excel文件的導(dǎo)入導(dǎo)出

    這篇文章主要介紹了SpringBoot中EasyExcel實現(xiàn)Excel文件的導(dǎo)入導(dǎo)出,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java編程接口回調(diào)一般用法代碼解析

    Java編程接口回調(diào)一般用法代碼解析

    本文的主要內(nèi)容是同過實際代碼向大家展示Java編程中接口回調(diào)的一般用法,具有一定參考價值,需要的朋友可以了解下
    2017-09-09

最新評論

正蓝旗| 普洱| 和顺县| 马关县| 石家庄市| 射阳县| 谷城县| 三穗县| 沧州市| 金门县| 平乡县| 天水市| 德昌县| 右玉县| 内黄县| 丁青县| 惠州市| 鄂托克旗| 神农架林区| 维西| 和顺县| 连城县| 中牟县| 平昌县| 普安县| 恭城| 潼南县| 黄梅县| 镇雄县| 同心县| 读书| 呼伦贝尔市| 光泽县| 房产| 凤凰县| 宁都县| 和硕县| 宜宾县| 双牌县| 察隅县| 平果县|