成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

還在重復(fù)創(chuàng)建對象?快試試通過享元模式減少對象創(chuàng)建

開發(fā) 前端
在實(shí)現(xiàn)享元模式時,通常會創(chuàng)建一個工廠類來管理共享的對象實(shí)例,并在需要時返回已存在的實(shí)例,而不是創(chuàng)建新的實(shí)例。這樣可以減少內(nèi)存占用,并且可以提高系統(tǒng)的性能。

享元模式

享元模式是一種結(jié)構(gòu)型設(shè)計模式,旨在通過共享盡可能多的數(shù)據(jù)來最小化內(nèi)存使用和提高性能。在享元模式中,對象被分為內(nèi)部狀態(tài)和外部狀態(tài)。內(nèi)部狀態(tài)是可以共享的,而外部狀態(tài)是根據(jù)對象的上下文而變化的。

在實(shí)現(xiàn)享元模式時,通常會創(chuàng)建一個工廠類來管理共享的對象實(shí)例,并在需要時返回已存在的實(shí)例,而不是創(chuàng)建新的實(shí)例。這樣可以減少內(nèi)存占用,并且可以提高系統(tǒng)的性能。

應(yīng)用場景

享元模式適用于需要共享大量對象、減少內(nèi)存占用、優(yōu)化性能的場景。

  1. 對象的數(shù)量非常大,且占用大量內(nèi)存。通過享元模式可以共享對象,減少內(nèi)存占用。
  2. 對象的大部分狀態(tài)可以外部狀態(tài),而少部分狀態(tài)可以內(nèi)部狀態(tài)。通過享元模式可以將內(nèi)部狀態(tài)和外部狀態(tài)分離,減少對象數(shù)量。
  3. 對象的狀態(tài)可以被多個對象共享。通過享元模式可以將狀態(tài)共享,減少重復(fù)創(chuàng)建對象。
  4. 對象的創(chuàng)建和銷毀頻繁,需要優(yōu)化性能。通過享元模式可以減少對象的創(chuàng)建和銷毀,提高性能。

場景示例

過年回家買火車票是一件很困難的事,無數(shù)人用刷票軟件向服務(wù)端發(fā)出請求,對于每一個請求服務(wù)器都必須做出應(yīng)答。在用戶設(shè)置好出發(fā)地和目的地之后,每次請求都返回一個查詢的車票結(jié)果。為了便于理解,我們假設(shè)每次返回的只有一趟列車的車票。那么當(dāng)數(shù)以萬計的人不問斷在請求數(shù)據(jù)時,如果每次都重新創(chuàng)建一個查詢的車票結(jié)果,那么必然會造成大量重復(fù)對象的創(chuàng)建、銷毀,使得 GC 任務(wù)繁重、內(nèi)存占用率高居不下。而這類問題通過享元模式就能夠得到很好地改善,從城市 A 到城市 B 的車輛是有限的,車上的鋪位也就是硬臥、硬臥、坐票 3 種。我們將這些可以公用的對象緩存起來,在用戶查詢時優(yōu)先使用緩存,如果沒有緩存則重新創(chuàng)建。這樣就將成千上萬的對象變?yōu)榱丝蛇x擇的有限數(shù)量。

首先我們創(chuàng)建一個 Ticket 接口,該接口定義展示車票信息的函數(shù):

public interface Ticket {
    public void showTicketInfo(String bunk);
}

它的一個具體的實(shí)現(xiàn)類是 TrainTicket 類:

class TrainTicket implements Ticket {
    public String from; // 始發(fā)地
    public String to; // 目的地
    public String bunk; // 鋪位
    public int price;

    TrainTicket(String from, String to) {
        this.from = from;
        this.to = to;
    }

    @Override
    public void showTicketInfo(String bunk) {
        price = new Random().nextInt(300);
        System.out.println("購買 從 " + from + " 到 " + to + "的 "
                + bunk + " 火車票" + ", 價格 : " + price);
    }
}

數(shù)據(jù)庫中表示火車票的信息有出發(fā)地、目的地、鋪位、價格等字段,在購票用戶每次查詢時如果沒有用某種緩存模式,那么返回車票數(shù)據(jù)的接口實(shí)現(xiàn)如下:

public class TicketFactory {

    public static Ticket getTicket(String from, String to) {
        return new TrainTicket(from, to);
    }
}

在 TicketFactory 的 getTicket 函數(shù)中每次會 new 一個 TrainTicket 對象,也就是說如果在短時間內(nèi)有 10000 萬用戶求購北京到杭州的車票,那么北京到杭州的車票對象就會被創(chuàng)建 10000 次,當(dāng)數(shù)據(jù)返回之后這些對象變得無用了又會被虛擬機(jī)回收。此時就會造成大量的重復(fù)對象存在內(nèi)存中,GC 對這些對象的回收也會非常消耗資源。如果用戶的請求量很大可能導(dǎo)致系統(tǒng)變得極其緩慢,甚至可能導(dǎo)致 OOM。正如上文所說,享元模式通過消息池的形式有效地減少了重復(fù)對象的存在。它通過內(nèi)部狀態(tài)標(biāo)識某個種類的對象,外部程序根據(jù)這個不會變化的內(nèi)部狀態(tài)從消息池中取出對象。使得同一類對象可以被復(fù)用,避免大量重復(fù)對象。

使用享元模式很簡單,只需要簡單地改造一下 TicketFactory,具體代碼如下:

/**
 * 車票工廠,以出發(fā)地和目的地為key緩存車票
 * 
 */
public class TicketFactory {

    static Map<String, Ticket> sTicketMap = new ConcurrentHashMap<String, Ticket>();

    public static Ticket getTicket(String from, String to) {
        String key = from + "-" + to;
        if (sTicketMap.containsKey(key)) {
            System.out.println("使用緩存 ==> " + key);
            return sTicketMap.get(key);
        } else {
            System.out.println("創(chuàng)建對象 ==> " + key);
            Ticket ticket = new TrainTicket(from, to);
            sTicketMap.put(key, ticket);
            return ticket;
        }
    }
}

在 TicketFactory 中添加了一個 map 容器,并且以出發(fā)地 + "-" + 日的地為鍵、以車票對象作為值存儲車票對象。這個 map 的鍵就是我們說的內(nèi)部狀態(tài),在這里就是出發(fā)地、橫杠、目的地拼接起來的字符串,如果沒有緩存則創(chuàng)建一個對象,并且將這個對象緩存到 map 中,下次再有這類請求時則直接從緩存中獲取。這樣即使有 10000 個請求北京到杭州的車票信息,那么出發(fā)地是北京、目的地是杭州的車票對象只有一個。這樣就從這個對象從 10000 減到了 1 個,避免了大量的內(nèi)存占用及頻繁的 GC 操作。簡單實(shí)現(xiàn)代碼如下:

public class Test {
    public static void main(String[] args) {
         Ticket ticket01 = TicketFactory.getTicket("北京", "杭州");
         ticket01.showTicketInfo("上鋪");
         Ticket ticket02 = TicketFactory.getTicket("北京", "杭州");
         ticket02.showTicketInfo("下鋪");
         Ticket ticket03 = TicketFactory.getTicket("北京", "杭州");
         ticket03.showTicketInfo("坐票");
    }
}

運(yùn)行輸出:

創(chuàng)建對象二=>北京-杭州
購買從北京到杭州的上鋪火車票,價格:28

使用緩存==>北京-杭州
購買從北京到杭州的下鋪火車票,價格:188

使用緩存==>北京-杭州
購買從北京到杭州的坐票火車票,價格:148

從輸出結(jié)果可以看到,只有第一次查詢車票時創(chuàng)建了一次對象,后續(xù)的查詢都使用的是消息池中的對象。這其實(shí)就是相當(dāng)于一個對象緩存,避免了對象的重復(fù)創(chuàng)建與回收。在這個例子中,內(nèi)部狀態(tài)就是出發(fā)地和目的地,內(nèi)部狀態(tài)不會發(fā)生變化;外部狀態(tài)就是鋪位和價格,價格會隨著鋪位的變化而變化。

在 JDK 中 String 也是類似消息池,我們知道在 Java 中 String 是存在于常量池中。也就是說一個 String 被定義之后它就被緩存到了常量池中,當(dāng)其他地方要使用同樣的字符串時,則直接使用的是緩存,而不會重復(fù)創(chuàng)建。例如下面這段代碼。

public class Test {

    public static void main(String[] args) {
        testString();
    }

    private static void testString() {
        String str1 = new String("abc");
        String str2 = "abc";
        String str3 = new String("abc");
        String str4 = "ab" + "c";
        // 使用equals只判定字符值
        System.out.println(str1.equals(str2));
        System.out.println(str1.equals(str3));
        System.out.println(str3.equals(str2));

        // 等號判等,判定兩個對象是不是同一個地址
        System.out.println(str1 == str2);
        System.out.println(str1 == str3);
        System.out.println(str3 == str2);
        System.out.println(str4 == str2);
    }
}

輸出:

true
true
true
false
false
false
true


責(zé)任編輯:武曉燕 來源: 沐雨花飛蝶
相關(guān)推薦

2016-06-20 11:32:27

JS原型class

2017-02-06 09:20:23

JavaScript實(shí)踐

2011-04-15 17:07:13

Java

2024-12-27 15:10:16

設(shè)計模式原型模式場景

2010-06-24 09:38:42

Windows備份云平臺

2020-05-25 10:20:19

享元模式場景

2021-03-08 08:40:25

Spring Bean 創(chuàng)建單例對象

2012-01-13 12:57:48

Java

2023-02-27 08:09:42

SpringAOP代理

2024-02-27 11:59:12

享元模式對象

2024-03-26 10:30:37

Mybatis擴(kuò)展庫API

2009-08-10 13:40:46

創(chuàng)建C# COM對象

2013-05-27 15:38:37

Java對象C++

2021-03-17 07:49:21

Java對象內(nèi)存

2009-05-19 14:13:46

.NET反射Assembly

2010-10-08 10:52:36

JavaScript對

2010-10-08 11:29:24

JavaScript對象

2021-05-27 11:26:46

nodesassCSS

2022-06-20 08:16:42

享元模式優(yōu)化系統(tǒng)內(nèi)存

2011-04-11 09:39:55

對象實(shí)例
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 98成人网 | 欧美一区二区免费 | 狠狠撸在线视频 | 欧美一区二区三区四区五区无卡码 | 久久久xxx | 天天看天天操 | 91精品国产91久久久久久 | 最新日韩精品 | 亚洲天堂一区二区 | www.99re| 欧美一级欧美一级在线播放 | 日韩成人高清在线 | 国产乱性| 色在线视频网站 | 日韩成人国产 | 91成人| 成人久久久 | 欧美一区二区在线观看 | 古典武侠第一页久久777 | 伊人久久精品 | 国产在线一区二 | 国产精品日韩 | 日韩精品色网 | 91九色porny首页最多播放 | 成人在线小视频 | 午夜99| 不卡一二区 | 另类亚洲视频 | 97精品国产97久久久久久免费 | 久久不卡区 | 免费在线观看av网站 | 91麻豆产精品久久久久久夏晴子 | 天堂男人av | 国产999精品久久久久久绿帽 | 亚洲男人天堂网 | 欧美久久一区二区三区 | 久久精品免费看 | 久久99精品久久久久久 | 亚洲一区二区在线视频 | 欧美日韩综合精品 | 亚洲免费在线 |