本篇文章給大家分享的是有關(guān)Java中享元模式的原理是什么,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
創(chuàng)新互聯(lián)主要從事成都做網(wǎng)站、成都網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)延平,十余年網(wǎng)站建設(shè)經(jīng)驗(yàn),價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):13518219792
1、關(guān)于享元模式
享元模式有點(diǎn)類似于單例模式,都是只生成一個對象被共享使用。享元模式主要目的就是讓多個對象實(shí)現(xiàn)共享,減少不會要額內(nèi)存消耗,將多個對同一對象的訪問集中起來,不必為每個訪問者創(chuàng)建一個單獨(dú)的對象,以此來降低內(nèi)存的消耗。
2、享元模式結(jié)構(gòu)圖
因?yàn)橄碓J浇Y(jié)構(gòu)比較復(fù)雜,一般結(jié)合工廠模式一起使用,在它的結(jié)構(gòu)圖中包含了一個享元工廠類。
在享元模式結(jié)構(gòu)圖中包含如下幾個角色:
Flyweight(抽象享元類):通常是一個接口或抽象類,在抽象享元類中聲明了具體享元類公共的方法,這些方法可以向外界提供享元對象的內(nèi)部數(shù)據(jù)(內(nèi)部狀態(tài)),同時也可以通過這些方法來設(shè)置外部數(shù)據(jù)(外部狀態(tài))。
ConcreteFlyweight(具體享元類):它實(shí)現(xiàn)了抽象享元類,其實(shí)例稱為享元對象;在具體享元類中為內(nèi)部狀態(tài)提供了存儲空間。通常我們可以結(jié)合單例模式來設(shè)計具體享元類,為每一個具體享元類提供唯一的享元對象。
UnsharedConcreteFlyweight(非共享具體享元類):并不是所有的抽象享元類的子類都需要被共享,不能被共享的子類可設(shè)計為非共享具體享元類;當(dāng)需要一個非共享具體享元類的對象時可以直接通過實(shí)例化創(chuàng)建。
FlyweightFactory(享元工廠類):享元工廠類用于創(chuàng)建并管理享元對象,它針對抽象享元類編程,將各種類型的具體享元對象存儲在一個享元池中,享元池一般設(shè)計為一個存儲“鍵值對”的集合(也可以是其他類型的集合),可以結(jié)合工廠模式進(jìn)行設(shè)計;當(dāng)用戶請求一個具體享元對象時,享元工廠提供一個存儲在享元池中已創(chuàng)建的實(shí)例或者創(chuàng)建一個新的實(shí)例(如果不存在的話),返回新創(chuàng)建的實(shí)例并將其存儲在享元池中。
3、享元模式的實(shí)現(xiàn)
在享元模式中引入了享元工廠類,享元工廠類的作用在于提供一個用于存儲享元對象的享元池,當(dāng)用戶需要對象時,首先從享元池中獲取,如果享元池中不存在,則創(chuàng)建一個新的享元對象返回給用戶,并在享元池中保存該新增對象。
接下來,實(shí)現(xiàn)一個登陸的享元模式。
1、用戶類
/** * 用戶類 * @author 董秀才 * */ public class User { private String username; // 用戶名 private String password; // 密碼 public User(String username,String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
2、抽象的登陸者(抽象享元類)
/** * 登陸者--抽象享元類 * @author 董秀才 * */ public abstract class Loginer { //登陸--享元類公共方法 public abstract void login(User user); }
3、具體的登陸者(具體享元類)
/** * 具體享元類 * @author 董秀才 * */ public class ConcreteLoginer extends Loginer{ // 登陸者憑證 private String loginerKey = ""; public ConcreteLoginer(String loginerKey) { this.loginerKey = loginerKey; } @Override public void login(User user) { System.out.println("登陸者憑證:" + this.loginerKey+",用戶名:" + user.getUsername() + ",密碼:" + user.getPassword()); } }
4、具體登陸者的工廠類(享元工廠類)
/** * 享元工廠類 * @author 董秀才 * */ public class ConcreteLoginerFactory { // map充當(dāng)對象享元池 private static MaploginerMap = new HashMap (); public static ConcreteLoginer getConcreteLoginer(String key) { // 從享元池中拿 登陸者對象 ConcreteLoginer concreteLoginer = loginerMap.get(key); // 如果享元池中沒有此對象 if(concreteLoginer == null) { // 創(chuàng)建對象 concreteLoginer = new ConcreteLoginer(key); // 存到享元池中 loginerMap.put(key, concreteLoginer); } // 返回對象 return concreteLoginer; } // 返回享元池對象數(shù)量 public static int getSize() { return loginerMap.size(); } }
5、測試類
/** * 博客測試類 * @author 董秀才 * */ public class MainTest { public static void main(String[] args) { // 去工廠拿對象 ConcreteLoginer concreteLoginer_1 = ConcreteLoginerFactory.getConcreteLoginer("csdn"); concreteLoginer_1.login(new User("董秀才","123456")); ConcreteLoginer concreteLoginer_2 = ConcreteLoginerFactory.getConcreteLoginer("csdn"); concreteLoginer_2.login(new User("董秀才","123456")); ConcreteLoginer concreteLoginer_3 = ConcreteLoginerFactory.getConcreteLoginer("csdn"); concreteLoginer_3.login(new User("董秀才","123456")); // 測試是否是同一個對象 System.out.println("是否是同一個對象:" + ((concreteLoginer_1==concreteLoginer_2)&&(concreteLoginer_2 == concreteLoginer_3))); // 第二登陸者 ConcreteLoginer concreteLoginer_4 = ConcreteLoginerFactory.getConcreteLoginer("博客園"); concreteLoginer_4.login(new User("董才才","654321")); ConcreteLoginer concreteLoginer_5 = ConcreteLoginerFactory.getConcreteLoginer("博客園"); concreteLoginer_5.login(new User("董才才","654321")); ConcreteLoginer concreteLoginer_6 = ConcreteLoginerFactory.getConcreteLoginer("博客園"); concreteLoginer_6.login(new User("董才才","654321")); System.out.println("是否是同一個對象:" + ((concreteLoginer_4==concreteLoginer_5)&&(concreteLoginer_5 == concreteLoginer_6))); // 工廠類中享元池中對象數(shù)量 System.out.println("享元池size:" + ConcreteLoginerFactory.getSize()); } }
6、運(yùn)行結(jié)果
4、總結(jié)
從上面代碼和運(yùn)行結(jié)果這可以看到,同一個登陸者登陸時是 "享" 用同一個登陸者對象。在享元對象池中只有兩個對象。
享元模式優(yōu)點(diǎn)
享元模式的外部狀態(tài)相對獨(dú)立,使得對象可以在不同的環(huán)境中被復(fù)用(共享對象可以適應(yīng)不同的外部環(huán)境)
享元模式可共享相同或相似的細(xì)粒度對象,從而減少了內(nèi)存消耗,同時降低了對象創(chuàng)建與垃圾回收的開銷
享元模式缺點(diǎn)
外部狀態(tài)由客戶端保存,共享對象讀取外部狀態(tài)的開銷可能比較大
享元模式要求將內(nèi)部狀態(tài)與外部狀態(tài)分離,這使得程序的邏輯復(fù)雜化,同時也增加了狀態(tài)維護(hù)成本
以上就是Java中享元模式的原理是什么,小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿姷交蛴玫降摹OM隳芡ㄟ^這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。