本文介紹了java設計模式之享元模式,供大家參考,具體內容如下
1、關于享元模式
享元模式有點類似于單例模式,都是只生成一個對象被共享使用。享元模式主要目的就是讓多個對象實現共享,減少不會要額內存消耗,將多個對同一對象的訪問集中起來,不必為每個訪問者創建一個單獨的對象,以此來降低內存的消耗。
2、享元模式結構圖
因為享元模式結構比較復雜,一般結合工廠模式一起使用,在它的結構圖中包含了一個享元工廠類。
在享元模式結構圖中包含如下幾個角色:
flyweight(抽象享元類):通常是一個接口或抽象類,在抽象享元類中聲明了具體享元類公共的方法,這些方法可以向外界提供享元對象的內部數據(內部狀態),同時也可以通過這些方法來設置外部數據(外部狀態)。
concreteflyweight(具體享元類):它實現了抽象享元類,其實例稱為享元對象;在具體享元類中為內部狀態提供了存儲空間。通常我們可以結合單例模式來設計具體享元類,為每一個具體享元類提供唯一的享元對象。
unsharedconcreteflyweight(非共享具體享元類):并不是所有的抽象享元類的子類都需要被共享,不能被共享的子類可設計為非共享具體享元類;當需要一個非共享具體享元類的對象時可以直接通過實例化創建。
flyweightfactory(享元工廠類):享元工廠類用于創建并管理享元對象,它針對抽象享元類編程,將各種類型的具體享元對象存儲在一個享元池中,享元池一般設計為一個存儲“鍵值對”的集合(也可以是其他類型的集合),可以結合工廠模式進行設計;當用戶請求一個具體享元對象時,享元工廠提供一個存儲在享元池中已創建的實例或者創建一個新的實例(如果不存在的話),返回新創建的實例并將其存儲在享元池中。
3、享元模式的實現
在享元模式中引入了享元工廠類,享元工廠類的作用在于提供一個用于存儲享元對象的享元池,當用戶需要對象時,首先從享元池中獲取,如果享元池中不存在,則創建一個新的享元對象返回給用戶,并在享元池中保存該新增對象。
接下來,實現一個登陸的享元模式。
1、用戶類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
/** * 用戶類 * @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、抽象的登陸者(抽象享元類)
1
2
3
4
5
6
7
8
9
10
11
|
/** * 登陸者--抽象享元類 * @author 董秀才 * */ public abstract class loginer { //登陸--享元類公共方法 public abstract void login(user user); } |
3、具體的登陸者(具體享元類)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
/** * 具體享元類 * @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、具體登陸者的工廠類(享元工廠類)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
/** * 享元工廠類 * @author 董秀才 * */ public class concreteloginerfactory { // map充當對象享元池 private static map<string,concreteloginer> loginermap = new hashmap<string, concreteloginer>(); public static concreteloginer getconcreteloginer(string key) { // 從享元池中拿 登陸者對象 concreteloginer concreteloginer = loginermap.get(key); // 如果享元池中沒有此對象 if (concreteloginer == null ) { // 創建對象 concreteloginer = new concreteloginer(key); // 存到享元池中 loginermap.put(key, concreteloginer); } // 返回對象 return concreteloginer; } // 返回享元池對象數量 public static int getsize() { return loginermap.size(); } } |
5、測試類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
/** * 博客測試類 * @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))); // 工廠類中享元池中對象數量 system.out.println( "享元池size:" + concreteloginerfactory.getsize()); } } |
6、運行結果
4、總結
從上面代碼和運行結果這可以看到,同一個登陸者登陸時是 "享" 用同一個登陸者對象。在享元對象池中只有兩個對象。
享元模式優點
享元模式的外部狀態相對獨立,使得對象可以在不同的環境中被復用(共享對象可以適應不同的外部環境)
享元模式可共享相同或相似的細粒度對象,從而減少了內存消耗,同時降低了對象創建與垃圾回收的開銷
享元模式缺點
外部狀態由客戶端保存,共享對象讀取外部狀態的開銷可能比較大
享元模式要求將內部狀態與外部狀態分離,這使得程序的邏輯復雜化,同時也增加了狀態維護成本
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://www.cnblogs.com/dongxiucai/p/9460069.html