zoukankan      html  css  js  c++  java
  • java设计模式——享元模式

    一. 定义与类型

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

    类型:结构性

    二. 使用场景

    (1)  常常应用于系统底层的开发,以便解决系统的性能问题

    (2)  系统有大量相似对象,需要缓冲池的场景

    三. 优缺点

    优点:

      (1) 减少对象的创建,降低内存中对象的数量,降低系统的内存,提高效率

      (2) 减少内存之外的其他资源占用

    缺点:

      (1) 关注内/外状态,关注线程安全问题

      (2) 使系统,程序的逻辑复杂化

    四.享元——扩展

    内部状态

    外部状态

    五. 相关设计模式

    享元模式和代理模式

      代理模式就是代理一个类,如果生成这个代理类需要花费的资源和时间比较多,就可以使用享元模式,提高系统的速度

    享元模式和单例模式

      单例模式中的容器单例就是享元模式的一种使用

    六. Coding

    以一个业务场景为例,假设每年年底的时候公司中的部门经理都需要写年终报告,但是可能不止要报告一次,需要重复报告。

    使用享元模式,可以很好的完成上面的例子。

    先创建一个接口:

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-12 10:01
     **/
    public interface Emplyee {
        void report();
    }

    再创建一个经理实体类,来实现接口

    /**
     * @program: designModel
     * @description: 部门manager
     * @author: YuKai Fan
     * @create: 2019-02-12 10:01
     **/
    public class Manager implements Emplyee {
        public void report() {
            System.out.println(reportContent);
        }
        private String title = "部门经理";
        private String department;//部门
        private String reportContent;//报告内容
    
        public Manager(String department) {
            this.department = department;
        }
    
        public void setReportContent(String reportContent) {
            this.reportContent = reportContent;
        }
    }

    在创建一个员工工厂,通过工厂在获取manager,因为只需要manager做报告,不需要employee。

    /**
     * @program: designModel
     * @description: 员工工厂
     * @author: YuKai Fan
     * @create: 2019-02-12 10:04
     **/
    public class EmployeeFactory {
       //因为在享元模式中,一般要考虑线程安全问题,但是还是要看业务场景来使用
    private static final Map<String, Emplyee> EMPLYEE_MAP = new HashMap<String, Emplyee>(); public static Emplyee getManager(String department) { Manager manager = (Manager) EMPLYEE_MAP.get(department); if (manager == null) { manager = new Manager(department); System.out.print("创建部门经理:" + department); String reportContent = department + "部门汇报:此次报告的主要内容是。。。。"; manager.setReportContent(reportContent); System.out.println(" 创建报告:" + reportContent); EMPLYEE_MAP.put(department, manager); } return manager; } }

    应用层:

    /**
     * @program: designModel
     * @description:
     * @author: YuKai Fan
     * @create: 2019-02-12 10:08
     **/
    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();
            }
        }
    }

    结果:

    UML类图:

    从结果可以看出,当部门经理做报告时只需要创建一次即可,下次不需要再次创建。减少了对象的创建

    在上面的代码例子中,department相当于外部状态。因为它依赖于外部的传入,为了方便理解,创建一个title属性,它就是一个内部状态,它不随外部状态department的变化而变化。

    七. 源码分析

    (1)

    Integer类就是典型的享元模式的例子

    Integer.valueOf中有一个IntegerCache,上面的代码中就对传入的值进行判断。如果是从IntegerCache中取出就直接返回,否则就new一个Integer对象。这也就是如果传入的int值不在固定的范围类,它们做==的时候一定是false,因为不是同一个对象。其中low=-128,high=127.

    还有Long类的valueOf,也是同上的道理。

    (2)

    tomcat中的GenericObjectPoolConfig连接池

  • 相关阅读:
    C++多线程chap3 多线程异步和通信1
    C++多线程chap2多线程通信和同步9
    C++多线程chap2多线程通信和同步5
    C++多线程chap3 多线程异步和通信2
    C++多线程chap2多线程通信和同步6
    taro实现多语言切换
    git常用命令
    pytorch hook 钩子
    MySQL 学习笔记(六)character 与 collation
    Python 学习笔记(七)socket
  • 原文地址:https://www.cnblogs.com/FanJava/p/10364314.html
Copyright © 2011-2022 走看看