精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何通過設(shè)計模式來節(jié)省內(nèi)存

科技綠洲 ? 來源:Java技術(shù)指北 ? 作者:Java技術(shù)指北 ? 2023-10-09 10:31 ? 次閱讀

相信大家日常開發(fā)過程中,一個優(yōu)秀的程序猿寫出的代碼一定要節(jié)省空間的,比如節(jié)省內(nèi)存,節(jié)省磁盤等等。那么如何通過設(shè)計模式來節(jié)省內(nèi)存呢?

1、什么是享元模式?

Use sharing to support large numbers of fine-grained objects efficiently.

享元模式(Flyweight Pattern):使用共享對象可有效地支持大量的細粒度的對象。

說人話:復(fù)用對象,節(jié)省內(nèi)存。

2、享元模式定義

圖片

①、Flyweight——抽象享元角色

是一個產(chǎn)品的抽象類, 同時定義出對象的外部狀態(tài)和內(nèi)部狀態(tài)的接口或?qū)崿F(xiàn)。

一個對象信息可以分為內(nèi)部狀態(tài)和外部狀態(tài)。

內(nèi)部狀態(tài) :對象可共享出來的信息, 存儲在享元對象內(nèi)部并且不會隨環(huán)境改變而改變,可以作為一個對象的動態(tài)附加信息, 不必直接儲存在具體某個對象中, 屬于可以共享的部分。

外部狀態(tài) :對象得以依賴的一個標(biāo)記, 是隨環(huán)境改變而改變的、 不可以共享的狀態(tài)。

②、ConcreteFlyweight——具體享元角色

具體的一個產(chǎn)品類, 實現(xiàn)抽象角色定義的業(yè)務(wù)。該角色中需要注意的是內(nèi)部狀態(tài)處理應(yīng)該與環(huán)境無關(guān), 不應(yīng)該出現(xiàn)一個操作改變了內(nèi)部狀態(tài), 同時修改了外部狀態(tài), 這是絕對不允許的。

③、unsharedConcreteFlyweight——不可共享的享元角色

不存在外部狀態(tài)或者安全要求(如線程安全) 不能夠使用共享技術(shù)的對象, 該對象一般不會出現(xiàn)在享元工廠中。

④、FlyweightFactory——享元工廠

職責(zé)非常簡單, 就是構(gòu)造一個池容器, 同時提供從池中獲得對象的方法。

3、享元模式通用代碼

/**
 * 抽象享元角色
 */
public abstract class Flyweight {
    // 內(nèi)部狀態(tài)
    private String instrinsic;

    // 外部狀態(tài) 通過 final 修改,防止修改
    protected final String extrinsic;

    protected Flyweight(String extrinsic) {
        this.extrinsic = extrinsic;
    }

    // 定義業(yè)務(wù)操作
    public abstract void operate();

    public String getInstrinsic() {
        return instrinsic;
    }

    public void setInstrinsic(String instrinsic) {
        this.instrinsic = instrinsic;
    }
}
/**
 * 具體享元角色1
 */
public class ConcreteFlyweight1 extends Flyweight{

    protected ConcreteFlyweight1(String extrinsic) {
        super(extrinsic);
    }

    @Override
    public void operate() {
        System.out.println("具體享元角色1");
    }
}
/**
 * 具體享元角色2
 */
public class ConcreteFlyweight2 extends Flyweight{

    protected ConcreteFlyweight2(String extrinsic) {
        super(extrinsic);
    }

    @Override
    public void operate() {
        System.out.println("具體享元角色2");
    }
}
public class FlyweightFactory {
    // 定義一個池容器
    private static HashMap< String,Flyweight > pool = new HashMap<  >();

    // 享元工廠
    public static Flyweight getFlyweight(String extrinsic){
        // 需要返回的對象
        Flyweight flyweight = null;
        // 池中沒有該對象
        if(pool.containsKey(extrinsic)){
            flyweight = pool.get(extrinsic);
        }else{
            // 根據(jù)外部狀態(tài)創(chuàng)建享元對象
            flyweight = new ConcreteFlyweight1(extrinsic);
            // 放置到池中
            pool.put(extrinsic,flyweight);
        }
        return flyweight;
    }
}

4、通過享元設(shè)計文本編輯器

假設(shè)文本編輯器只包含文字編輯功能,而且只記錄文字和格式兩部分信息,其中格式包括文字的字體型號、大小、顏色等信息。

4.1 普通實現(xiàn)

通常設(shè)計是把每個文字看成一個單獨對象。

package com.itcoke.designpattern.flyweight.edittext;

/**
 * 單個文字對象
 */
public class Character {
    // 字符
    private char c;
    // 字體型號
    private String font;
    // 字體大小
    private int size;
    // 字體顏色
    private int colorRGB;

    public Character(char c, String font, int size, int colorRGB){
        this.c = c;
        this.font = font;
        this.size = size;
        this.colorRGB = colorRGB;
    }

    @Override
    public String toString() {
        return String.valueOf(c);
    }
}
/**
 * 編輯器實現(xiàn)
 */
public class Editor {
    private ArrayList< Character > chars = new ArrayList<  >();

    public void appendCharacter(char c, String font, int size, int colorRGB){
        Character character = new Character(c,font,size,colorRGB);
        chars.add(character);
    }

    public void display(){
        System.out.println(chars);
    }
}

客戶端:

public class EditorClient {
    public static void main(String[] args) {
        Editor editor = new Editor();
        editor.appendCharacter('A',"宋體",11,0XFFB6C1);
        editor.appendCharacter('B',"宋體",11,0XFFB6C1);
        editor.appendCharacter('C',"宋體",11,0XFFB6C1);
        editor.display();
    }
}

4.2 享元模式改寫

上面的問題很容易發(fā)現(xiàn),每一個字符就會創(chuàng)建一個 Character 對象,如果是幾百萬個字符,那內(nèi)存中就會存在幾百萬的對象,那怎么去節(jié)省這些內(nèi)存呢?

其實,分析一下,對于字體的格式,通常不會有很多,于是我們可以把字體格式設(shè)置為享元,也就是上面說的可以共享的內(nèi)部狀態(tài)。

內(nèi)部狀態(tài)(共享):字體類型、大小、顏色

外部狀態(tài)(不共享):字符

于是代碼改寫如下:

public class CharacterStyle {
    // 字體型號
    private String font;
    // 字體大小
    private int size;
    // 字體顏色
    private int colorRGB;

    public CharacterStyle(String font, int size, int colorRGB) {
        this.font = font;
        this.size = size;
        this.colorRGB = colorRGB;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CharacterStyle that = (CharacterStyle) o;
        return size == that.size &&
                colorRGB == that.colorRGB &&
                Objects.equals(font, that.font);
    }

    @Override
    public int hashCode() {
        return Objects.hash(font, size, colorRGB);
    }
}
public class CharacterStyleFactory {

    private static final Map< CharacterStyle,CharacterStyle > mapStyles = new HashMap<  >();

    public static CharacterStyle getStyle(String font, int size, int colorRGB){
        CharacterStyle newStyle = new CharacterStyle(font,size,colorRGB);

        if(mapStyles.containsKey(newStyle)){
            return mapStyles.get(newStyle);
        }
        mapStyles.put(newStyle,newStyle);
        return newStyle;
    }
}
public class Character {
    private char c;
    private CharacterStyle style;

    public Character(char c, CharacterStyle style) {
        this.c = c;
        this.style = style;
    }

    @Override
    public String toString() {
        return String.valueOf(c);
    }
}
public class Editor {
    private List< Character > chars = new ArrayList<  >();

    public void appendCharacter(char c, String font, int size, int colorRGB){
        Character character = new Character(c,CharacterStyleFactory.getStyle(font,size,colorRGB));
        chars.add(character);
    }

    public void display(){
        System.out.println(chars);
    }
}

5、享元模式在 java.lang.Integer 中應(yīng)用

看下面這段代碼,打印結(jié)果是啥?

public class IntegerTest {
    public static void main(String[] args) {
        Integer i1 = 56;
        Integer i2 = 56;
        Integer i3 = 129;
        Integer i4 = 129;
        System.out.println(i1 == i2); 
        System.out.println(i3 == i4); 
    }
}

圖片

為什么是這種結(jié)果呢?

首先說一下 Integer i = 59;底層執(zhí)行了:Integer i = Integer.valueOf(59); 這是自動裝箱。

int j = i; 底層執(zhí)行了:int j = i.intValue(); 這是自動拆箱。

然后我們Integer.valueOf() 方法:

圖片

再看 IntegerCache 源碼:

private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

其實這就是我們前面說的享元對象的工廠類,緩存 -128 到 127 之間的整型值,這是最常用的一部分整型值,當(dāng)然JDK 也提供了方法來讓我們可以自定義緩存的最大值。

6、享元模式優(yōu)點

減少應(yīng)用程序創(chuàng)建的對象, 降低程序內(nèi)存的占用, 增強程序的性能。

但它同時也提高了系統(tǒng)復(fù)雜性, 需要分離出外部狀態(tài)和內(nèi)部狀態(tài), 而且外部狀態(tài)具有固化特性, 不應(yīng)該隨內(nèi)部狀態(tài)改變而改變, 否則導(dǎo)致系統(tǒng)的邏輯混亂。

7、享元模式應(yīng)用場景

①、系統(tǒng)中存在大量的相似對象。

②、細粒度的對象都具備較接近的外部狀態(tài), 而且內(nèi)部狀態(tài)與環(huán)境無關(guān), 也就是說對象沒有特定身份。

③、需要緩沖池的場景。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    2999

    瀏覽量

    73882
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4747

    瀏覽量

    68348
  • 設(shè)計模式
    +關(guān)注

    關(guān)注

    0

    文章

    53

    瀏覽量

    8622
  • 線程
    +關(guān)注

    關(guān)注

    0

    文章

    504

    瀏覽量

    19651
收藏 人收藏

    評論

    相關(guān)推薦

    為了節(jié)省內(nèi)存OLED不使用全緩沖模式了.

    電源智慧辦公
    甘草酸不酸
    發(fā)布于 :2022年03月10日 15:12:17

    windowsXP系統(tǒng)如何節(jié)省內(nèi)存的方法

    windowsXP系統(tǒng)如何節(jié)省內(nèi)存的方法  XP系統(tǒng)節(jié)省內(nèi)存,加快開機速度的方法如下:1.禁用壓縮文件夾功能,2.減少開機磁盤掃描等待時間,重啟時候馬上你會看到效果。3.刪除系統(tǒng)備份文件,在各種
    發(fā)表于 02-26 15:40

    如何用PIC24FJ128GC010設(shè)置EEPROM

    嗨,我正試圖使用數(shù)據(jù)EEPROM仿真與MYPIC24FJ128GC010,按此。但是,我發(fā)現(xiàn)我不能在編程之間節(jié)省內(nèi)存。在項目設(shè)置中(我使用MPLABX V3.30),我看不到設(shè)置EEPROM的設(shè)置
    發(fā)表于 04-29 14:04

    分享一個MCU省內(nèi)存的辦法

    1、聊一聊以前聽這首曲子內(nèi)心會變得格外平靜,然而現(xiàn)在卻五味陳雜!今天主要跟大家分享一個MCU省內(nèi)存的辦法,同時也歡迎大家在文末問答留言討論。2、讀前必備對于MCU...
    發(fā)表于 11-01 08:48

    分享一個MCU省內(nèi)存的辦法

    今天主要跟大家分享一個MCU省內(nèi)存的辦法,同時也歡迎大家在文末問答留言討論。本文補充省內(nèi)存辦法1const的使用關(guān)于const的用法應(yīng)該是老生常談的知識點了,如果還有不是特別清楚的小伙伴可以參考一文
    發(fā)表于 11-03 06:58

    單片機開發(fā)之節(jié)省內(nèi)存大法

    提點一下,我一說估計很多人都清楚了,不過時間久了一些簡單的知識沒有去使用或者重溫,到了解決問題的時候還是容易卡殼,如果還沒有看過以前文章的可以到下面鏈接看看:?單片機開發(fā)之節(jié)省內(nèi)存大法(...
    發(fā)表于 01-25 07:08

    ARM是怎樣使用多種低功耗模式節(jié)省功耗的

    三種電源模式 :運行、 睡眠、深度睡眠三種。一般而言,對于基于 ARM 架構(gòu)的 MCU 在系統(tǒng)或者電源復(fù)位之后,CPU 處于運行狀態(tài)。當(dāng) CPU 不需要再繼續(xù)運行時,可以使用多種低功耗模式節(jié)
    發(fā)表于 02-11 07:26

    iar build時出現(xiàn)內(nèi)存不夠的問題

    單片機小白,語言是C,在用iar建工程的時候出現(xiàn)如圖錯誤,根據(jù)其他提問更改了優(yōu)化等級仍未解決,請問還有其他解決方法嗎?或者有什么能優(yōu)化代碼節(jié)省內(nèi)存的算法舉例或者學(xué)習(xí)資料推薦?謝謝!
    發(fā)表于 03-26 21:49

    有沒有用tls省內(nèi)存的方案啊

    上傳文件走tls加密,測下來整個流程最大會分配50K內(nèi)存,這對于整個內(nèi)存只有80多k的單片機簡直災(zāi)難,有沒有用tls省內(nèi)存的方案。
    發(fā)表于 09-30 10:07

    嵌入式系統(tǒng)節(jié)省內(nèi)存的解決方法

    嵌入式系統(tǒng)內(nèi)存往往是有限制的(成本考慮),因此需要盡量支持更多的功能,同時盡量減少使用的內(nèi)存
    的頭像 發(fā)表于 06-28 11:57 ?3223次閱讀
    嵌入式系統(tǒng)<b class='flag-5'>節(jié)省內(nèi)存</b>的解決方法

    【MCU】一種單片機節(jié)省內(nèi)存的方法(補充)

    1、聊一聊 以前聽這首曲子內(nèi)心會變得格外平靜,然而現(xiàn)在卻五味陳雜! 今天主要跟大家分享一個MCU省內(nèi)存的辦法,同時也歡迎大家在文末問答留言討論。2、讀前必備 對于MCU...
    發(fā)表于 10-26 19:51 ?14次下載
    【MCU】一種單片機<b class='flag-5'>節(jié)省內(nèi)存</b>的方法(補充)

    單片機單口不可用或被占用_【MCU】一種單片機節(jié)省內(nèi)存的方法

    今天主要跟大家分享一個MCU省內(nèi)存的辦法,同時也歡迎大家在文末問答留言討論。本文補充省內(nèi)存辦法1const的使用 關(guān)于const的用法應(yīng)該是老生常談的知識點了,如果還有不是特別清楚的小伙伴可以
    發(fā)表于 10-28 16:21 ?15次下載
    單片機單口不可用或被占用_【MCU】一種單片機<b class='flag-5'>節(jié)省內(nèi)存</b>的方法

    Chrome將全面推出“節(jié)省內(nèi)存”和“節(jié)省電量”模式

    這個功能就像手機的 “超級省電模式”,適用于筆記本電腦電池電量不足,開啟省電模式后,當(dāng)設(shè)備電池電量達到 20% 時,Chrome 將通過限制后天活動和帶動畫 / 視頻的網(wǎng)站的視覺效果
    的頭像 發(fā)表于 12-12 14:44 ?869次閱讀

    如何使用Redis更節(jié)省內(nèi)存

    當(dāng)你的業(yè)務(wù)應(yīng)用在 Redis 中存儲數(shù)據(jù)很少時,你可能并不太關(guān)心內(nèi)存資源的使用情況。但隨著業(yè)務(wù)的發(fā)展,你的業(yè)務(wù)存儲在 Redis 中的數(shù)據(jù)就會越來越多。
    的頭像 發(fā)表于 12-19 15:41 ?911次閱讀

    如何通過在汽車子系統(tǒng)中共享麥克風(fēng)節(jié)省空間和BOM成本

    電子發(fā)燒友網(wǎng)站提供《如何通過在汽車子系統(tǒng)中共享麥克風(fēng)節(jié)省空間和BOM成本.pdf》資料免費下載
    發(fā)表于 09-14 10:58 ?0次下載
    如何<b class='flag-5'>通過</b>在汽車子系統(tǒng)中共享麥克風(fēng)<b class='flag-5'>來</b><b class='flag-5'>節(jié)省</b>空間和BOM成本