享元模式的定義:用共享的技術有效地支持大量細粒度的對象。java
認識享元模式:web
一、變與不變緩存
享元模式的設計重點就在於分享變與不變。把一個對象分離爲內部狀態和外部狀態,內部狀態是不變的,外部狀態是可變的。而後經過共享不變的部分,以達到節約空間的目的。安全
二、共享與不共享ide
在享元模式中,又有共享和不共享之分。有時還能夠把共享的享元對象組合成一個組合對象,這樣的組合對象能夠不用共享,須要時建立他就能夠了。this
三、內部狀態和外部狀態設計
內部狀態是享元對象內部的屬性、狀態,是不變的,因此能夠共享。code
外部狀態是享元對象外部的狀態,取決於使用的場景,會根據使用場景而變化,因此不能夠共享。對象
四、實例池接口
在享元模式中,會建立一個享元工廠,用它來管理、建立和清理享元對象。享元對象就緩存在這個工廠中。這個享元工廠的難度在於什麼時候清理再也不須要或者是長時間再也不須要的享元對象,能夠選擇使用長時間不用的享元對象,就把它清理掉。
示例代碼:
一、示例說明:
這裏有兩個名詞:(1)安全實體:就是被權限系統檢測的對象,如「工資數據」;(2)權限:就是要被校驗的權限對象。如「查看」和「編輯」。
此示例是一個模擬登陸後,用戶有不一樣的系統訪問權限。當用戶登陸後,會將用戶的權限保存到系統內存中或web程序的Session中。可是系統爲了節約不變的對象,
即可用享元模式去保存相同的對象。如:
張三有「查看」「工資數據」的權限。
李四有「查看」「工資數據」的權限。
《「查看」「工資數據」的權限》,不一樣的人均可以有這個權限,但並不須要爲每一個人都實例化一個這樣的權限對象,將這個對象保存到內存中,以免用戶每次操做都去檢查是否有權限。
爲了節約空間,即可把這樣不變的對象設置成享元對象,讓全部的用戶共享。
這樣,用戶登陸後,將權限保存到享元工廠中。用戶每次到享元工廠中拿對應的權限比對,檢查是否有權限作對應的操做。
(1)享元接口
package gof.flyweight; /** * <p> * 享元接口 * </p> * * @author andy */ public interface Flyweight { boolean match(String security, String permit); }
(2)享元對象的實現
package gof.flyweight; /** * <p> * 享元對象的實現 * </p> * * @author andy * */ public class AuthorizationFlyweight implements Flyweight { /** * 內部狀態,安全實體 */ private String security = "";; /** * 內部狀態,權限 */ private String permit = "";; /** * @return the security */ public String getSecurity() { return security; } /** * @return the permit */ public String getPermit() { return permit; } public AuthorizationFlyweight(String state) { String[] data = state.split(","); if (data.length == 2) { this.security = data[0]; this.permit = data[1]; } } @Override public boolean match(String security, String permit) { if (this.security.equals(security) && this.permit.equals(permit)) { return true; } return false; } }
(3)享元對象的管理工廠
package gof.flyweight; import java.util.HashMap; import java.util.Map; /** * <p> * 享元對象的管理工廠 * </p> * * @author andy * */ public class FlyweightFactory { /** * 緩存享元實例 */ private Map<String, Flyweight> flyweightMap = new HashMap<String, Flyweight>(); private static FlyweightFactory instance = new FlyweightFactory(); private FlyweightFactory() { } public static FlyweightFactory getInstance() { return instance; } public Flyweight getFlyweight(String key) { Flyweight result = null; result = flyweightMap.get(key); if (result == null) { Flyweight f = new AuthorizationFlyweight(key); flyweightMap.put(key, f); result = f; } return result; } }
(4)處理用戶請求
package gof.flyweight; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; /** * <p> * 安全管理 * </p> * * @author andy * */ public class SecurityManager { private static SecurityManager instance = new SecurityManager(); // 存儲用戶對應的僅限 private Map<String, Collection<Flyweight>> map = new HashMap<String, Collection<Flyweight>>(); private SecurityManager() { } public static SecurityManager getInstance() { return instance; } public void login(String user) { Collection<Flyweight> securitys = querySecurityByUser(user); map.put(user, securitys); } private Collection<Flyweight> querySecurityByUser(String user) { List<Flyweight> result = new ArrayList<Flyweight>(); for (String strs : TestDB.cols) { String[] str = strs.split(","); if (str[0].equals(user)) { result.add(FlyweightFactory.getInstance().getFlyweight(str[1] + "," + str[2])); } } return result; } public boolean hasPermit(String user, String security, String permit) { boolean result = false; Collection<Flyweight> flys = map.get(user); if (flys == null) { return false; } for (Flyweight f : flys) { if (f.match(security, permit)) { System.out.println("享元對象flyweight=" + f); result = true; break; } } return result; } }
(5)模擬DB數據
package gof.flyweight; import java.util.ArrayList; import java.util.Collection; /** * <p> * 模擬DB數據 * </p> * * @author andy * */ public class TestDB { public static Collection<String> cols = new ArrayList<String>(); static { cols.add("張三,人員列表,查看"); cols.add("張三,薪資結構,查看"); cols.add("李四,人員列表,查看"); cols.add("李四,薪資結構,編輯"); cols.add("李四,人員列表,編輯"); for (int i = 0; i < 3; i++) { cols.add("張三" + i + ",薪資結構,查看"); } } }