`

读《研磨设计模式》-代码笔记-享元模式-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

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

    设计模式Golang实现《研磨设计模式》读书笔记.zip

    设计模式Golang实现《研磨设计模式》读书笔记Go语言设计模式Go语言设计模式的实例代码创建模式工厂简单模式(Simple Factory)工厂方法模式(工厂方法)抽象工厂模式(Abstract Factory)创建者模式(Builder)原型...

    研磨设计模式源码

    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#编程中,享元模式尤其适用于那些创建大量相似对象且内存消耗较大的场景。本篇文章将深入探讨享元模式...

Global site tag (gtag.js) - Google Analytics