溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java描述設(shè)計(jì)模式(18):享元模式

發(fā)布時(shí)間:2020-05-17 19:30:15 來(lái)源:網(wǎng)絡(luò) 閱讀:157 作者:知了一笑 欄目:編程語(yǔ)言

本文源碼:GitHub·點(diǎn)這里 || GitEE·點(diǎn)這里

一、使用場(chǎng)景

應(yīng)用代碼

public class C01_InScene {
    public static void main(String[] args) {
        String c0 = "cicada" ;
        String c1 = "cicada" ;
        System.out.println(c0 == c1); // true
    }
}

String類(lèi)型就是使用享元模式。String對(duì)象是final類(lèi)型,對(duì)象一旦創(chuàng)建就不可改變。在JAVA中字符串常量都是存在常量池中的,JAVA會(huì)確保一個(gè)字符串常量在常量池中只有一個(gè)拷貝,其中c0和c1就是一個(gè)字符串常量。結(jié)果為:true,說(shuō)明c0和c1兩個(gè)引用都指向了常量池中的同一個(gè)字符串常量"cicada"。這樣的設(shè)計(jì)避免了在創(chuàng)建N多相同對(duì)象時(shí)所產(chǎn)生的不必要的大量的資源消耗。

二、享元模式

1、基礎(chǔ)簡(jiǎn)介

享元模式是對(duì)象的結(jié)構(gòu)模式。享元模式以共享的方式高效地支持大量的細(xì)粒度對(duì)象。常用于系統(tǒng)底層開(kāi)發(fā),解決系統(tǒng)的性能問(wèn)題。像數(shù)據(jù)庫(kù)連接池,里面都是創(chuàng)建好的連接對(duì)象,在這些連接對(duì)象中有需要的則直接拿來(lái)用,避免重新創(chuàng)建。

2、模式圖解

Java描述設(shè)計(jì)模式(18):享元模式

3、核心角色

  • 抽象享元角色

給出一個(gè)抽象接口,以規(guī)定具體享元角色要實(shí)現(xiàn)的方法。

  • 具體享元角色

實(shí)現(xiàn)抽象享元角色所規(guī)定出的接口。如果有內(nèi)部狀態(tài)的話,必須為內(nèi)部狀態(tài)提供存儲(chǔ)能力。

  • 享元工廠角色

負(fù)責(zé)創(chuàng)建和管理享元角色。必須保證享元對(duì)象可以被系統(tǒng)選擇性共享。當(dāng)一個(gè)客戶端對(duì)象調(diào)用一個(gè)享元對(duì)象的時(shí)候,享元工廠角色會(huì)檢查系統(tǒng)中是否已經(jīng)有一個(gè)符合要求的享元對(duì)象。如果已經(jīng)存在,直接返回該對(duì)象;如果系統(tǒng)中沒(méi)有該享元對(duì)象,享元工廠角色就應(yīng)當(dāng)創(chuàng)建該享元對(duì)象。

4、內(nèi)部外部狀態(tài)

  • 內(nèi)部狀態(tài)指對(duì)象共享出來(lái)的信息,存儲(chǔ)在享元對(duì)象內(nèi)部且不會(huì)隨環(huán)境的改變而改變。
  • 外部狀態(tài)指對(duì)象得以依賴(lài)的一個(gè)標(biāo)記,可以隨環(huán)境改變而改變的、不可共享的狀態(tài)。

5、源碼實(shí)現(xiàn)

public class C02_FlyWeight {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight fly = factory.factoryMethod('c');
        fly.printState("One");
        fly = factory.factoryMethod('d');
        fly.printState("Two");
        fly = factory.factoryMethod('c');
        fly.printState("San");
        // 調(diào)用了三次工廠方法,只創(chuàng)建了兩個(gè)對(duì)象
        factory.poolInfo();
    }
}
/**
 * 抽象享元角色類(lèi)
 */
interface Flyweight {
    void printState (String state);
}
/**
 * 具體享元角色類(lèi)
 */
class ConcreteFlyweight implements Flyweight {
    private Character innerState = null;
    public ConcreteFlyweight (Character state){
        this.innerState = state;
    }
    @Override
    public void printState(String state) {
        System.out.println("內(nèi)部狀態(tài):" + this.innerState);
        System.out.println("外部狀態(tài):" + state);
    }
}
/**
 * 享元工廠角色類(lèi)
 */
class FlyweightFactory {
    // 模擬數(shù)據(jù)池
    private Map<Character,Flyweight> pool = new HashMap<>();
    public Flyweight factoryMethod (Character state){
        //先從緩存中查找對(duì)象
        Flyweight fly = pool.get(state);
        if(fly == null){
            fly = new ConcreteFlyweight(state);
            pool.put(state, fly);
        }
        return fly;
    }
    public void poolInfo (){
        System.out.println("數(shù)據(jù)池:"+pool);
    }
}

三、JDK應(yīng)用場(chǎng)景

  • 測(cè)試代碼塊
    public class C03_Integer {
    public static void main(String[] args) {
        Integer c1 = Integer.valueOf(127),c2 = Integer.valueOf(127) ;
        Integer c3 = new Integer(127),c4 = new Integer(127) ;
        boolean flag1 = c1==c2 ,flag2 = c2==c3,flag3 = c3==c4 ;
        // true;false;false
        System.out.println(flag1+";"+flag2+";"+flag3);
        Integer c5 = Integer.valueOf(222),c6=Integer.valueOf(222) ;
        // false
        System.out.println(c5==c6);
    }
    }
  • 源碼分析
    public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
    }

    這里valueOf方法的意思就是,如果傳入的數(shù)據(jù)在 (-128) 到 (127) 之間,則從緩存中直接返回,否則創(chuàng)建一個(gè)新的Integer對(duì)象。

四、模式總結(jié)

享元模式能夠解決重復(fù)對(duì)象的內(nèi)存浪費(fèi)的問(wèn)題,當(dāng)系統(tǒng)中有大量相似對(duì)象,需要緩沖池時(shí)。不需一直創(chuàng)建新對(duì)象,可以從緩沖池里拿。這樣可以降低系統(tǒng)內(nèi)存,同時(shí)提高效率。經(jīng)典的應(yīng)用場(chǎng)景就是池技術(shù),String常量池、數(shù)據(jù)庫(kù)連接池、緩沖池等等都是享元模式的應(yīng)用,享元模式是池技術(shù)的重要實(shí)現(xiàn)方式。享元模式使得系統(tǒng)更加復(fù)雜。為了使對(duì)象可以共享,需要時(shí)刻管理對(duì)象的狀態(tài)變化,這使得程序的邏輯變得復(fù)雜。

五、源代碼地址

GitHub·地址
https://github.com/cicadasmile/model-arithmetic-parent
GitEE·地址
https://gitee.com/cicadasmile/model-arithmetic-parent

Java描述設(shè)計(jì)模式(18):享元模式

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI