享元模式翅雏,屬于結構性模式。
享元模式人芽,享:共享望几,分享;元:元件萤厅,對象的意思橄抹。整體意思就是共享對象。
在JVM中惕味,能實現(xiàn)共享對象的部分楼誓,有靜態(tài)區(qū)和常量池,而我們今天說的享元模式正好是利用靜態(tài)區(qū)內(nèi)存來共享對象名挥。
UML圖:
我們先看JDK中的代碼疟羹,java.lang包下面有我們的基本數(shù)據(jù)類型的裝箱類,比如:Short禀倔,Integer榄融,Byte,Long等等救湖。我們看如下代碼:
Byte類中ValueOf(byte b)方法
Byte的內(nèi)部靜態(tài)類ByteCache:
圖中可以看出愧杯,ByteCache對象在被使用之前,已經(jīng)通過靜態(tài)代碼塊鞋既,在ByteCache類里面已經(jīng)初始化并添加-128到128長度的靜態(tài)數(shù)組力九。Byte對象用valueOf方法實例化對象的時候耍铜,直接從靜態(tài)數(shù)組chache里面獲取值,不用每次都用new關鍵字來創(chuàng)建畏邢,節(jié)約了棧內(nèi)存和對內(nèi)存空間业扒。
這也是享元模式的目的:在有大量對象時,有可能會造成內(nèi)存溢出(注意這里是溢出不是泄露)舒萎,我們把其中共同的部分抽象出來程储,如果有相同的業(yè)務請求,直接返回在內(nèi)存中已有的對象臂寝,避免重新創(chuàng)建章鲤,節(jié)約了內(nèi)存空間。
有人會問咆贬,對象里面有些屬性是可以共享的比如人的性別败徊,這種屬性選擇性比較少;但是人的名字比較多掏缎,做共享是不是不合適呢皱蹦?對的,這里我們可以根據(jù)對象細粒度來分為對象的內(nèi)部狀態(tài)和外部狀態(tài)眷蜈。
內(nèi)部狀態(tài):指對象共享出來的信息沪哺,存儲在享元對象內(nèi)部并且不會隨環(huán)境的改變而改變;
外部狀態(tài):指對象得以依賴的一個標記酌儒,是隨環(huán)境改變而改變的辜妓、不可共享的狀態(tài)。
比如: 1:象棋上每個子的角色可以作為內(nèi)部狀態(tài)忌怎,而象棋里面招式可以作為外部狀態(tài)籍滴。
? ? ? ? ? ? ?2:衣服的顏色,款式可以作為內(nèi)部狀態(tài)榴啸,而衣服的歸屬人可以作為外部狀態(tài)孽惰。
? ? ? ? ? ? ?3:游戲里面角色可以作為內(nèi)部狀態(tài),而用戶自定義的名稱可作為外部狀態(tài)鸥印。
今天還是以游戲《完美國際》為例灰瞻,演示一下享元模式,我們知道完美國際游戲選擇職業(yè)之后辅甥,用戶要給角色取名酝润,這里的職業(yè)可以看過是內(nèi)部狀態(tài)(被共享部分),而用戶取的角色名稱可以看做是外部狀態(tài)(完全由用戶自己定義)璃弄。
職業(yè)選擇接口:
用戶自定義角色對象和名稱:
外部狀態(tài):
內(nèi)部狀態(tài)(工廠):
測試:
上面圖中,