模式说明
实际上,我认为这个并不是一个为了代码设计而诞生的设计模式,更多的是解决数据问题。那么什么是享元模式呢?相对于单例,享元就相当于多个单例的集合,也就是说对象以共享的方式对外提供使用。由于是共享的方式,那么可以使程序更加节省内存,但相对的,因为享元模式中的对象由于在程序启动时就初始化,因此这些对象会一直进驻在内存,这也需要按实际情况来设计享元对象的数量。
应用场景
Spring MVC 中的所有 Controller 默认是单例,而共享的方式为所有请求提供服务,值得一提的是,Spring 内的 Service 默认也是单例,而共享的方式为所有 Controller 提供服务。棋牌游戏里的棋子和扑克都可以使用享元模式,因为棋子和扑克都是可以预先创建的单例集合,只是在棋盘和扑克桌子上被不同位置引用。在 Java 里的枚举类型,我也认为是符合享元设计。
代码实现
现在我们以系统管理员角色为例,利用享元模式的优势进行设计。每一种角色都是不同的权限集合,如用户操作相关的权限,设置特定规则的权限等等。
public class Role {
private String name; // 名称唯一
private Permission permission;
public Role(String name, Permission permission) {
this.name = name;
this.permission = permission;
}
// ... getter / setter ...
}
public class Permission {
private boolean userCreate;
private boolean addFilterRules;
private boolean superAdmin; // 超级管理员
// ... 更多的权限 ...
}
public class RoleFactory {
static Map<String, Role> roleMap;
static {
roleMap = loadRolesFromDB();
}
public static Role getRole(String name) {
return roleMap.get(name);
}
}
假设角色就是从数据库中获取,那么我们就可以通过静态的 Role Map 记录并缓存起来,当管理员进行登录时我们即可通过 RoleFactory 获取相应的 Role 角色,可以看出 Role Map 都是共享对象,因此无需管理员登录时重新创建,仅在应用启动时消耗一些时间和内存而已。当然了,RoleFactory 还不足以应对角色创建、更新、删除问题,这就需要引入相应的 Role Map 维护操作了,不在此处展开。