美文网首页
结构型模式——享元模式(四)

结构型模式——享元模式(四)

作者: 最后的轻语_dd43 | 来源:发表于2019-05-23 08:39 被阅读0次

    该项目源码地址:https://github.com/lastwhispers/code/tree/master/java-basic/design-pattern
    (设计模式相关代码与笔记)

    1. 定义

    提供了减少对象数且从而改善应用所需的对象结构的方式。运用共享技术有效地支持大是细粒度的对象。

    2. 适用场景

    • 常常应用于系统底层的开发,以便解决系统的性能问题。
    • 系统有大量相似对象、需要缓冲池的场景。

    比如:String常量池、Integer常量池、数据库连接池、线程池

    3. 类图与角色

    享元模式类图

    享元模式存在如下几个角色:

    Flyweight:抽象享元类。所有具体享元类的超类或者接口,通过这个接口,Flyweight可以接受并作用于外部专题 。

    ConcreteFlyweight:具体享元类。指定内部状态,为内部状态增加存储空间。

    UnsharedConcreteFlyweight:非共享具体享元类。指出那些不需要共享的Flyweight子类。

    FlyweightFactory:享元工厂类。用来创建并管理Flyweight对象,它主要用来确保合理地共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory就会提供一个已经创建的Flyweight对象或者新建一个(如果不存在)。

    享元模式的核心在于享元工厂类,享元工厂类的作用在于提供一个用于存储享元对象的享元池,用户需要对象时,首先从享元池中获取,如果享元池中不存在,则创建一个新的享元对象返回给用户,并在享元池中保存该新增对象。

    4. 内部状态与外部状态

    内部状态:在享元对象内部不随外界环境改变而改变的共享部分

    外部状态:随着环境的改变而改变,不能够共享的状态就是外部状态

    5. 相关设计模式

    享元模式和代理模式

    • 代理模式生成的代理类,可以使用享元模式来生成代理类。

    享元模式和单例模式

    • 享元模式可以再次创建对象,也可以取缓存对象。单例模式则是严格控制只有一个实例对象。
    • 享元模式可以通过自己实现对外部的单例,也可以在需要的使用创建更多的对象。单例模式是自身控制,需要增加不属于该对象本身的逻辑。

    6. 模式实例

    背景:公司要求各个部门的管理者做一下年底总结报告,如果这些报告都已经生成过了,那么我们就没有必要再去new一个了;我们通过这么一个场景来体现一下享元模式:

    6.1 模式基本结构

    抽象享元类 有一个员工接口:

    public interface Employee {
        void report();
    }
    

    具体享元类 还有一个经理类:

    public class Manager implements Employee {
    
        private String department;
        private String reportContent;
    
        public Manager(String department) {
            this.department = department;
        }
        /** 我们可以在外部来重置年终报告 */
        public void setReportContent(String reportContent) {
            this.reportContent = reportContent;
        }
    
        @Override
        public void report() {
            System.out.println(reportContent);
        }
    }
    

    享元工厂类 还有一个经理工厂类:

    public class EmployeeFactory {
        /**
         * 定义一个池容器
         */
        private static final Map<String, Employee> EMPLOYEE_MAP = new HashMap<>();
    
        /**
         * 享元工厂
         *
         * @param department
         * @return
         */
        public static Employee getManager(String department) {
            Manager manager = (Manager) EMPLOYEE_MAP.get(department);
            if (manager == null) {
                manager = new Manager(department);
                System.out.print("创建部门经理" + department);
                String reportContent = department + "部门汇报:此次报告的主要内容是......";
                manager.setReportContent(reportContent);
                System.out.println(" 创建报告" + reportContent);
                //享元工厂
                EMPLOYEE_MAP.put(department, manager);
            }
            return manager;
        }
    }
    

    测试:

    public class Test {
        private static final String departments[] = {"RD","QA","PM","BD"};
    
        public static void main(String[]args){
            for (int i = 0; i < 10; i++) {
                String department = departments[(int) (Math.random() * departments.length)];
                Manager manager = (Manager) EmployeeFactory.getManager(department);
                manager.report();
            }    
        }
    }
    

    测试结果:

    测试结果

    此时类图:

    类图

    6.2 内部状态与外部状态

    内部状态:在享元对象内部不随外界环境改变而改变的共享部分
    外部状态:随着环境的改变而改变,不能够共享的状态就是外部状态
    对于Manager雷,成员变量department就是外部状态,随着Manager的变化而变化。title是内部状态,Manager怎么变,title也不会变化。

    public class Manager implements Employee {
        /**
         * 内部状态
         */
        private String title = "部门经理";
        /**
         * 外部状态
         */
        private String department;
        private String reportContent;
    
        public Manager(String department) {
            this.department = department;
        }
    
        /**
         * 我们可以在外部来重置年终报告
         */
        public void setReportContent(String reportContent) {
            this.reportContent = reportContent;
        }
    
        @Override
        public void report() {
            System.out.println(reportContent);
        }
    }
    

    7. 优缺点

    优点:

    • 减少对象的创建,降低内存中对象的数量,降低系统的内存,提高效率
    • 减少内存之外的其他资源占用

    缺点:

    • 享元的对象无法拥有独立的行为
    • 关注内/外部状态、关注线程安全问题
    • 使系统、程序的逻辑复杂化

    8. 模式总结

    1、享元模式可以极大地减少系统中对象的数量。但是它可能会引起系统的逻辑更加复杂化。
    2、享元模式的核心在于享元工厂,它主要用来确保合理地共享享元对象。
    3、内部状态为不变共享部分,存储于享元享元对象内部,而外部状态是可变部分,它应由客户端来负责。

    9. 扩展-JDK1.7以及框架源码中的享元模式

    9.1 Integer类里面的valueOf方法与IntegerCache;
    valueOf方法与IntegerCache分析
    9.2 tomcat的连接池:GenericObjectPoolConfig
    org.apache.commons.pool2.impl.GenericKeyedObjectPool

    相关文章

      网友评论

          本文标题:结构型模式——享元模式(四)

          本文链接:https://www.haomeiwen.com/subject/qhmmzqtx.html