`

读《研磨设计模式》-代码笔记-享元模式-Flyweight

阅读更多
声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/





import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/*
 * 个人理解:
 * 1、Flyweight模式其实就是缓存:把公用的、可共享的数据缓存(示例里面把数据存放在一个单例的Map里面)
 * 2、不需共享的享元对象:因为这些对象是Flyweight的组合,Flyweight已经共享了,就不需要重复缓存了
 * 	  例如:操作薪资数据=查看薪资数据+修改薪资数据
 */

/**
 * Flyweight模式的主要原理就在这里
 * 假设要描述“张三拥有薪资数据的查看权限”“李四拥有薪资数据的查看权限”,“王五拥有薪资数据的查看权限”……
 * 我们很容易看出,“薪资数据的查看权限”是可共享的。我们把它定义为IFlyweight接口,并将它缓存在一个HashMap里面:
 */
enum FlyweightFactory {
    
    INSTANCE;
    
    //Map<"薪资数据,查看",IFlyweight(entity="薪资数据",permission="查看")>
    private Map<String, IFlyweight> flyweightMap = new HashMap<String, IFlyweight>();
    
    public IFlyweight getFlyweight(String state) {
        IFlyweight flyweight = flyweightMap.get(state);
        if (flyweight == null) {
            flyweight = new AuthorizationFlyweight(state);
            flyweightMap.put(state, flyweight);
        }
        return flyweight;
    }
}


//要共享的数据-接口
interface IFlyweight {
	
	/**
	 * 验证是否对该“安全实体”有权限
	 * @param securityEntity 安全实体,即需要保证安全的数据,访问时要做访问控制,例如,工资数据
	 * @param permission	权限描述,例如:查看、修改等等
	 * @return true 表示通过 false表示不通过
	 */
	boolean testify(String securityEntity, String permission);
	
	//这个方法是提供给“不需共享的对象”的。“共享对象”不支持这个方法(throw unsupportException)
	void add(IFlyweight flyweight);
	
	//返回Flyweight的描述
	String getDescription();
}


//要共享的数据-具体实现类
class AuthorizationFlyweight implements IFlyweight {

	private String securityEntity;
	private String permission;
	
	public boolean testify(String securityEntity, String permission) {
		return this.securityEntity.equals(securityEntity)
				&& this.permission.equals(permission);
	}
	
	//e.g. state="薪资数据,查看"
	public AuthorizationFlyweight(String state) {
		String[] states = state.split(",");
		this.securityEntity = states[0];
		this.permission = states[1];
	}
	
	public String getSecurityEntity() {
		return securityEntity;
	}

	public String getPermission() {
		return permission;
	}

	public void add(IFlyweight flyweight) {
		throw new UnsupportedOperationException("对象不支持此功能");
	}

	public String getDescription() {
		return permission + securityEntity;
	}
}


//不需共享的数据
class UnsharedFlyweight implements IFlyweight {

	//保存了一系列的“共享对象”
	private List<IFlyweight> list = new ArrayList<IFlyweight>();
	
	public void add(IFlyweight flyweight) {
		list.add(flyweight);
	}

	public boolean testify(String securityEntity, String permission) {
		for (IFlyweight flyweight : list) {
			if (flyweight.testify(securityEntity, permission)) {
				return true;
			}
		}
		return false;
	}

	public String getDescription() {
		StringBuilder sb = new StringBuilder("(组合权限 ");
		for (IFlyweight flyweight : list) {
			sb.append(flyweight.getDescription()).append("=").append(flyweight).append(" ");
		}
		sb.append(")\n");
		return sb.toString();
	}
}


enum SecurityManagement {
	
	INSTANCE;
	
	//Map<用户名,用户权限> 在web应用中,这些数据通常存放在session中
	private Map<String, Collection<IFlyweight>> userPermissionMap = new HashMap<String, Collection<IFlyweight>>();
	
	//登录时查询并缓存用户拥有的权限
	public void login(String user) {
		Collection<IFlyweight> permissions = this.getPermissionsOf(user);
		userPermissionMap.put(user, permissions);
	}
	
	//begin-只测试“共享”
	private Collection<IFlyweight> getPermissionsOf(String user) {
		Collection<IFlyweight> permissions = new ArrayList<IFlyweight>();
		for (String data : TestDB.dataList) {
			String[] datas = data.split(",");
			String userName = datas[0];
			String securityEntity = datas[1];
			String permission = datas[2];
			if (userName.equals(user)) {
				String state = securityEntity + "," + permission;
				//从缓存中取数据。如果缓存中没有,就把这个数据保存在缓存中
				IFlyweight flyweight = FlyweightFactory.INSTANCE.getFlyweight(state);
				permissions.add(flyweight);
			}
		}
		return permissions;
	}
	
	public void login2(String user) {
		Collection<IFlyweight> permissions = this.getPermissionsOf2(user);
		userPermissionMap.put(user, permissions);
	}
	//end
	
	//begin-同时测试“共享”和“不共享”
	private Collection<IFlyweight> getPermissionsOf2(String user) {
		Collection<IFlyweight> permissions = new ArrayList<IFlyweight>();
		for (String data : TestDB2.dataList) {
			String[] datas = data.split(",");
			String userName = datas[0];
			String securityEntity = datas[1];
			String permission = datas[2];
			String type = datas[3];
			if (userName.equals(user)) {
				IFlyweight flyweight = null;
				String state = null;
				if (type.equals("2")) {		//表示是组合类型的授权
					state = securityEntity + permission;
					flyweight = new UnsharedFlyweight();
					String[] composites = TestDB2.dataMap.get(state);
					for (String composite : composites) {
						//“共享对象”的组合。“共享对象”从缓存中取出
						IFlyweight singleFlyweight = FlyweightFactory.INSTANCE.getFlyweight(composite);
						flyweight.add(singleFlyweight);
					}
				} else {
					state = securityEntity + "," + permission;
					flyweight = FlyweightFactory.INSTANCE.getFlyweight(state);
				}
				permissions.add(flyweight);
			}
		}
		return permissions;
	}
	//end
	
	public boolean hasPermission(String user, String securityEntity, String permission) {
		System.out.println("现在验证:"+ user + securityEntity + permission);
		boolean result = false;
		Collection<IFlyweight> flyweightCollection = userPermissionMap.get(user);
		if (flyweightCollection == null || flyweightCollection.size() == 0) {
			System.out.println(user + "没有登陆或是没有分配任何权限");
			result = false;
		} else {
			System.out.println("拥有的权限:");
			for (IFlyweight flyweight : flyweightCollection) {
				System.out.println(flyweight.getDescription()+ ";flyweight = " + flyweight);
				if (flyweight.testify(securityEntity, permission)) {
					result = true;
					break;
				}
			}
		}
		return result;
	}
}


//数据库1-共享
class TestDB{
	public static Collection<String> dataList = new ArrayList<String>();
	static {
		dataList.add("张三,人员列表,查看");
		dataList.add("李四,人员列表,查看 ");
		dataList.add("李四,薪资数据,查看");
		dataList.add("李四,薪资数据,修改");
		dataList.add("张三1,人员列表,查看");
		dataList.add("张三2,人员列表,查看");
		dataList.add("张三3,人员列表,查看");
	}
}


//数据库2-同时有共享和不共享的数据。增加了一个字段表示权限类型是单个权限(1)还是组合权限(2)
class TestDB2{
	public static Collection<String> dataList = new ArrayList<String>();
	public static Map<String, String[]> dataMap = new HashMap<String, String[]>();
	static {
		dataList.add("张三,人员列表,查看,1");
		dataList.add("张三1,人员列表,查看,1");
		dataList.add("张三2,人员列表,查看,1");
		dataList.add("张三3,人员列表,查看,1");
		dataList.add("李四,人员列表,查看,1");
		
		dataList.add("李四,薪资数据,查看,1");	//a
		dataList.add("李四,薪资数据,修改,1"); //b	(a+b刚好是“薪资数据操作”;实际应用中不应该这样存储)
		dataList.add("张三,薪资数据,操作,2");
		
		dataMap.put("薪资数据操作", new String[]{"薪资数据,查看","薪资数据,修改"});
	}
}



//这个类是用来测试的
public class FlyweightPattern {

	public static void main(String[] args) {
		SecurityManagement  securityManagement = SecurityManagement.INSTANCE;
		/*//测试“共享”
		securityManagement.login("张三");
		securityManagement.login("张三1");
		securityManagement.login("张三2");
		securityManagement.login("张三3");
		securityManagement.login("李四");
		
		boolean b1 = securityManagement.hasPermission("张三", "薪资数据", "查看");
		boolean b2 = securityManagement.hasPermission("李四", "薪资数据", "查看");
		System.out.println(b1 + "," + b2);
		
		//可以看到下面这四句,输出flyweight时,是同一个flyweight,表明缓存被使用了
		System.out.println(securityManagement.hasPermission("张三", "人员列表", "查看"));
		System.out.println(securityManagement.hasPermission("张三1", "人员列表", "查看"));
		System.out.println(securityManagement.hasPermission("张三2", "人员列表", "查看"));
		System.out.println(securityManagement.hasPermission("张三3", "人员列表", "查看"));
		*/
		
		//测试“共享”和“不共享的对象”
		securityManagement.login2("张三");
		securityManagement.login2("张三1");
		securityManagement.login2("张三2");
		securityManagement.login2("张三3");
		securityManagement.login2("李四");
		
		//可以看到,张三“薪资数据操作”所包含的“薪资数据查看”、“薪资数据修改”这两个flyweight与李四的是同一对象
		System.out.println(securityManagement.hasPermission("张三", "薪资数据", "修改"));
		System.out.println(securityManagement.hasPermission("张三", "薪资数据", "查看"));
		System.out.println(securityManagement.hasPermission("李四", "薪资数据", "修改"));
		System.out.println(securityManagement.hasPermission("李四", "薪资数据", "查看"));
		
		System.out.println(securityManagement.hasPermission("李四", "人员列表", "修改"));
		
		//不能直接测试“操作”
		//System.out.println(securityManagement.hasPermission("张三", "薪资数据", "操作"));
		
	}

}


0
0
分享到:
评论

相关推荐

    设计模式学习笔记--Flyweight享元模式.docx

    享元模式是一种设计模式,属于构造型模式,其主要目的是减少对象的数量,通过共享大量相似对象的内部状态来节省内存。这种模式在处理大量细粒度对象时特别有用,能够有效地提高系统的性能。 享元模式的核心是...

    研磨设计模式源码

    10. **享元模式**:运用共享技术有效地支持大量细粒度的对象。这可能涉及到一个Flyweight类,存储共享状态,以及一个享元工厂来管理这些对象。 以上只是设计模式中的一部分,实际源码中可能涵盖了更多模式。通过...

    c++设计模式-结构型模式-享元模式

    c++设计模式-结构型模式-享元模式;qt工程;c++简单源码; 享元(Flyweight)模式的定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类...

    研磨设计模式-part2

    第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) ...

    研磨设计模式-part4

    第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) ...

    研磨设计模式-part3

    第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) ...

    设计模式专题之(十二)享元模式---设计模式享元模式示例代码(python--c++)

    享元模式是一种结构型设计模式,它通过共享已有对象来减少内存中对象的数量,从而达到提高系统性能的目的。在大型软件系统中,特别是在处理大量相似对象时,享元模式能够有效地减少内存开销,提高系统运行效率。在这...

    设计模式精解-GoF-23种设计模式解析--附C++源代码

    - 享元模式(Flyweight):使用共享对象,有效地支持大量细粒度的对象。 3. **行为型模式**:这类模式关注对象之间的责任分配。 - 责任链模式(Chain of Responsibility):避免将请求的发送者和接收者耦合在一起...

    c++-设计模式之享元模式(Flyweight)

    享元模式(Flyweight Pattern)是一种结构型设计模式,用于减少创建大量小对象所带来的内存开销。通过共享对象,享元模式能够有效地支持大量细粒度的对象,减少内存使用并提高性能。它常用于需要大量重复对象的场景...

    研磨设计模式(完整带书签).part2.pdf

    第20章 享元模式(Flyweight) 第21章 解释器模式(Interpreter) 第22章 装饰模式(Decorator) 第23章 职责链模式(Chain of Responsibility) 第24章 桥接模式(Bridge) 第25章 访问者模式(Visitor) ...

    java设计模式---诙谐易懂版

    代理模式(Proxy Pattern)、单例模式(Singleton Pattern)、工厂方法模式(Factory Method Pattern)、抽象工厂模式(Abstract Factory ...)、享元模式(Flyweight Pattern)、备忘录模式(Memento Pattern)等...

    6.设计模式-享元模式1

    设计模式-享元模式 设计模式是软件设计中的一种解决方案,旨在提高代码的可维护性、灵活性和可重用性。享元模式(Flyweight Pattern)是结构型模式的一种,主要用于减少大量相似对象的内存占用,提高系统的性能和...

    研磨设计模式博文集

    2. **结构型模式**:这些模式关注如何将类和对象组合成更大的结构,如适配器模式(Adapter)、桥接模式(Bridge)、装饰器模式(Decorator)、外观模式(Facade)、享元模式(Flyweight)、组合模式(Composite)和...

    设计模式专题---设计模式示例代码(全)(python--c++)

    9. **Flyweight模式**:Flyweight模式属于结构型设计模式,用于减少大量细粒度对象的创建,通过共享对象来支持大量的对象实例,特别适用于内存有限的环境。 10. **Iterator模式**:Iterator模式是一种行为设计模式...

    设计模式----命令模式

    享元模式通常与Flyweight接口、Concrete Flyweight(具体享元)、Flyweight Factory(享元工厂)三个角色一起工作,工厂负责创建和管理享元对象,确保享元对象的复用,避免因创建过多的实例导致内存开销过大。...

    学习php设计模式 php实现享元模式(flyweight)

    享元模式(Flyweight Pattern)是软件设计中的一种结构型设计模式,它通过共享技术来支持大量细粒度的对象,以此来降低内存中对象的数量。在PHP中实现享元模式,可以帮助我们优化程序性能,特别是在对象数目过多时,...

    享元模式flyweight

    享元模式(Flyweight Pattern)是一种结构型设计模式,它能有效地减少系统中对象的数量,从而降低内存消耗,提高性能。这种模式通过共享大量相似对象的内部状态来达到这一目标,而只保留对象的外部状态在外部管理。...

    JAVA设计模式-chm版

    包括适配器模式(Adapter)、桥接模式(Bridge)、装饰器模式(Decorator)、外观模式(Facade)、组合模式(Composite)、享元模式(Flyweight)和代理模式(Proxy)。这些模式可以帮助我们更好地组织代码,实现...

    设计模式(C#)之享元模式(Flyweight Pattern)

    享元模式是设计模式中的一种结构型模式,它主要通过共享已有对象来减少内存中对象的数量,从而提高系统性能。在C#编程中,享元模式尤其适用于那些创建大量相似对象且内存消耗较大的场景。本篇文章将深入探讨享元模式...

    设计模式之轻量级Flyweight

    通过分析和运行这些测试代码,我们可以更深入地理解享元模式的工作原理及其在性能优化方面的效果。 总之,Flyweight模式是一种有效的设计策略,通过共享对象来节省资源,尤其适用于处理大量相似对象的情况。理解并...

Global site tag (gtag.js) - Google Analytics