• 软件设计模式白话文系列(十一)享元模式


    1、描述

    以共享的方法高效地支持大量细粒度对象的复用。在 Java 中,通过提前初始化对象或者首次使用后记录对象,后续使用就可以复用对象来实现享元模式。类似缓存技术。

    2、模式结构

    • 享元对象:可复用对象。

    • 享元工厂类:享元对象的工厂类,负责创建、储存享元对象。客户端从工厂类请求对象有则返回,没有则创建

      一个放入工厂类。例如 String 类的缓存池和数据库的连接池。

    3、实现逻辑

    享元模式实现的关键是需要区分对象的内蕴状态和外蕴状态。简单点解释就是,内蕴状态就是可被共享的部分;外蕴状态就是不可共享的部分,需要客户端提供的部分。Java 中实现享元模式,就是把内蕴部分剥离出来静态化,客户端调用时提供外蕴状态(当然对象可以没有外蕴部分)。

    4、实战代码

    RBAC 模型基于角色的权限控制。通过角色关联用户,角色关联权限的方式间接赋予用户权限。

    我们知道对于用户来讲,每个用户都有自己的 编号、姓名,但是会存在多个用户都是同一个角色。在这里编号、姓名就属于外蕴状态,而角色就属于内蕴状态。

    /**
     * 享元对象
     *
     * @author Eajur.Wen
     * @version 1.0
     * @date 2022-11-15 19:01:20
     */
    @Data
    public class Role {
        private String name;
    
        private List permissions;
    }
    
    /**
     * 业务对象
     *
     * @author Eajur.Wen
     * @version 1.0
     * @date 2022-11-15 19:00:57
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Member {
    
        private Long id;
        private String name;
    
        private Role role;
    }
    
    /**
     * 享元工厂类
     * 这里结合静态内部类单例模式实现 RoleFactory
     *
     * @author Eajur.Wen
     * @version 1.0
     * @date 2022-11-15 19:04:47
     */
    public class RoleFactory {
        private static Map roleMap = new HashMap<>();
    
        public RoleFactory() {
            Role admin = new Role();
            admin.setName("admin");
            admin.setPermissions(List.of("add", "update", "select", "delete"));
    
            Role user = new Role();
            user.setName("user");
            user.setPermissions(List.of("select"));
    
            roleMap.put("admin", admin);
            roleMap.put("user", user);
        }
    
        public Role getRole(String name) {
            return roleMap.get(name);
        }
    
        public static final RoleFactory getInstance() {
            return SingletonHolder.INSTANCE;
        }
    
        private static class SingletonHolder {
            private static final RoleFactory INSTANCE = new RoleFactory();
        }
    }
    
    /**
     * 测试类
     *
     * @author Eajur.Wen
     * @version 1.0
     * @date 2022-11-15 19:13:48
     */
    public class Client {
        public static void main(String[] args) {
            // 创建 10 个 Admin 用户
            for (int i = 0; i < 10; i++) {
                Member member = new Member((long) i,
                        "admin" + i,
                        RoleFactory.getInstance().getRole("admin"));
                System.out.println(member);
            }
            System.out.println("------------------");
            // 创建 100 个 User 用户
            for (int i = 0; i < 100; i++) {
                Member member = new Member((long) i,
                        "user" + i,
                        RoleFactory.getInstance().getRole("user"));
                System.out.println(member);
            }
        }
    }
    

    这样我们通过提前创建 role 对象,使得频繁创建 member 对象时复用 role 对象,减少了 role 对象的频繁创建与销毁,大大节约了内存占用。

    5、适用场景

    相同对象或者相似对象需要频繁创建时,适合使用享元模式。

    6、享元模式与单例模式的区别

    单例模式的目的是为了确保一个类只存在一个对象,需要自行实例化并提供全局访问方法。

    享元模式的目的是为了对对象内蕴部分的复用,无需保证一个类只存在一个对象。

  • 相关阅读:
    8个独立键盘驱动程
    驱动开发,stm32mp157a开发板的led灯控制实验(再优化),使用ioctl函数,通过字符设备驱动分步注册方式编写LED驱动,完成设备文件和设备的绑定
    R语言从入门到精通Day2之【R语言软件下载与安装】
    Jmeter吞吐量控制器使用小结
    js添加 删除 替换 插入节点所用的方法。js常用的几种事件。
    重组蛋白表达的几种形式
    基于单片机智能防触电装置的研究与设计
    RecyclerView源码解析(二):结合LinearLayout分析绘制流程
    pytorch数据处理工具箱
    离散数学 --- 二元关系 --- 关系的性质和关系的闭包
  • 原文地址:https://www.cnblogs.com/eajur/p/16895857.html