-------android培訓、JAVA培訓、期待與您交流!
----------
享元模式的結構
通過學習,對享元設計模式不太瞭解,那麼現在整理如下內容:
享元模式採用一個共享來避免大量擁有相同內容對象的開銷。這種開銷最常見、最直觀的就是內存的損耗。享元對象能做到共享的關鍵是區分內蘊狀態(Internal State)和
外蘊狀態(External State)。
一個內蘊狀態是存儲在享元對象內部的,並且是不會隨環境的改變而有所不同。因此,一個享元可以具有內蘊狀態並可以共享。
一個外蘊狀態是隨環境的改變而改變的、不可以共享的。享元對象的外蘊狀態必須由客戶端保存,並在享元對象被創建之後,在需要使用的時候再傳入到享元對象內部。外
蘊狀態不可以影響享元對象的內蘊狀態,它們是相互獨立的。
享元模式的優點:減少對象數量,節省內存空間。
享元模式的缺點:維護共享對象,需要額外的開銷(用一個線程來維護垃圾回收)。
享元模式的本質:分離與共享
何時使用享元模式:
如果一個應用程序使用了大量的細粒度對象,可以使用享元模式來減少對象數量。
如果使用大量的對象,造成很大的存儲開銷,可以使用享元模式來減少對象數量,並節約內存。
如果對象的大多數狀態都可以轉變爲外部狀態,可以使用享元對象來實現外部狀態與內部狀態的分離。
享元模式可以分成單純享元模式和複合享元模式兩種形式。
單純享元模式
在單純的享元模式中,所有的享元對象都是可以共享的。抽象享元(Flyweight)角色 :給出一個抽象接口,以規定出所有具體享元角色需要實現的方法。
具體享元(ConcreteFlyweight)角色:實現抽象享元角色所規定出的接口。如果有內蘊狀態的話,必須負責爲內蘊狀態提供存儲空間。
享元工廠(FlyweightFactory)角色 :本角色負責創建和管理享元角色。本角色必須保證享元對象可以被系統適當地共享。當一個客戶端對象調用一個享元對象的
時候,享元工廠角色會檢查系統中是否 已經有一個符合要求的享元對象。如果已經有了,享元工廠角色就應當提供這個已有的享元對象;如果系統中沒有一個適當的享元對象
的話,享元工廠角色就應當創 建一個合適的享元對象。
好了,廢話不多說,直接上代碼,首先抽象一個場景:
公司的管理層和普通員工對員工的信息有不同的權限。管理層可以修改員工的個人信息,普員工只能查看不能修改,擅自修改系統會給出提示。員工的個人信息是可以共享的,但是起職能範圍和操作權限可以被管理層修改。
抽象享元角色:
- public interface IFlyWeight {
- /**
- * 判斷傳入的安全實體和權限,是否和享元對象內部狀態匹配
- * 參數 securityEntity 和 permit 是外蘊對象
- * @param securityEntity
- * @param permit
- * @return
- */
- public boolean match(String securityEntity, String permit);
- }
具體享元角色:
- public class AuthorizationFlyweight implements IFlyWeight {
- /**
- * 內蘊對象,安全實體
- */
- private String mSecurityEntity;
- /**
- * 內蘊對象,權限
- */
- private String mPermit;
- public AuthorizationFlyweight(String state) {
- String str[] = state.split(",");
- this.mSecurityEntity = str[0];
- this.mPermit = str[1];
- }
- @Override
- public boolean match(String securityEntity, String permit) {
- if (mSecurityEntity.equals(securityEntity) && mPermit.equals(permit)) {
- return true;
- }
- return false;
- }
- }
- public class FlyWeightFactory {
- private static FlyWeightFactory mFactory = new FlyWeightFactory();
- private FlyWeightFactory() {
- }
- public static FlyWeightFactory getInstance() {
- return mFactory;
- }
- /**
- * 緩存多個人IFlyWeight 對象
- */
- private Map<String, IFlyWeight> flyMap = new HashMap<String, IFlyWeight>();
- /**
- * 獲取享元單元
- * @param key
- * @return
- */
- public IFlyWeight getFlyWeight(String key) {
- IFlyWeight fly = flyMap.get(key);
- if(fly==null){
- fly = new AuthorizationFlyweight(key);
- flyMap.put(key, fly);
- }
- return fly;
- }
- }
- public class SecurityManager {
- private static SecurityManager manager = new SecurityManager();
- private SecurityManager() {
- }
- public static SecurityManager getInstance() {
- return manager;
- }
- /**
- * 存放登錄人員的權限
- */
- private Map<String, Collection<IFlyWeight>> map = new HashMap<String, Collection<IFlyWeight>>();
- public void logon(String user) {
- Collection<IFlyWeight> coll = queryByUser(user);
- map.put(user, coll);
- }
- /**
- * 從數據庫中獲取某人所有的權限
- *
- * @param user
- * @return
- */
- private Collection<IFlyWeight> queryByUser(String user) {
- Collection<IFlyWeight> coll = new ArrayList<IFlyWeight>();
- for (String s : TestDB.coll) {
- String str[] = s.split(",");
- if (str[0].equals(user)) {
- IFlyWeight fly = FlyWeightFactory.getInstance().getFlyWeight(
- str[1] + "," + str[2]);
- coll.add(fly);
- }
- }
- return coll;
- }
- /**
- * 判斷某個用戶對某個安全實體是否有某種權限
- *
- * @param user
- * 用戶
- * @param securityEntity
- * 安全實體
- * @param permit
- * 權限
- * @return
- */
- public boolean hasPermit(String user, String securityEntity, String permit) {
- Collection<IFlyWeight> coll = map.get(user);
- if (coll == null || coll.size() == 0) {
- System.out.println(user + "沒有登錄或者沒有該權限...");
- return false;
- }
- for (IFlyWeight fly : coll) {
- if (fly.match(securityEntity, permit)) {
- return true;
- }
- }
- return false;
- }
- }
- public class TestDB {
- public static Collection<String> coll = new ArrayList<String>();
- static {
- coll.add("張三,人員列表,查看");
- coll.add("李四,人員列表,查看");
- coll.add("李四,薪資列表,查看");
- coll.add("李四,薪資列表,修改");
- for (short i = 0; i < 3; i++) {
- coll.add("張三" + i + ",人員列表,查看");
- }
- }
- }
具體的實現,本例子是基於android實現的,java只單獨寫一個Test類在main裏面實現就行了:
- SecurityManager manager = SecurityManager.getInstance();
- manager.logon("張三");
- manager.logon("李四");
- boolean b1 = manager.hasPermit("張三", "薪資列表", "查看");
- boolean b2 = manager.hasPermit("李四", "薪資列表", "查看");
- boolean b3 = manager.hasPermit("張三", "人員列表", "查看");
- System.out.println("b1 = "+b1);
- System.out.println("b2 = "+b2);
- System.out.println("b3 = "+b3);
從數據庫中可以看出來,張三是人事的普通員工,只能查看公司在職人員,對員工的薪資無權限查看,b1返回false,b3返回true
李四是人事普通員工兼財務主管,可以修改查詢員工薪資並且可以查看在職員工信息,b2返回true
如果
- boolean b4 = manager.hasPermit("王武", "人員列表", "查看");
因爲“王武”這個人沒有登錄,所以提示信息是 “沒有登錄或者沒有該權限...”
-------android培訓、JAVA培訓、期待與您交流!
----------
--------詳細請查看www.itheima.com-------------