一. 定义与类型

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

类型:结构性

二. 使用场景

(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连接池

最新文章

  1. linux 内核源代码
  2. Python Windows环境下安装Python集成开发环境 学习之路(一)
  3. 【JS】defer / async
  4. WCF学习笔记之地址
  5. Redis源代码分析(二十八)--- object创建和释放redisObject物
  6. 11g R2RAC Dynamic remastering
  7. linux视频学习7(ssh, linux启动过程分析,加解压缩,java网络编程)
  8. ASP.NET Core MVC和Visual Studio入门
  9. 企业IT管理员IE11升级指南【12】—— 兼容视图列表介绍
  10. 【题解】Luogu P4121 [WC2005]双面棋盘
  11. php单点登录
  12. Kotlin 使用类似C# 的yield功能
  13. Navicat远程连接不上mysql解决方案
  14. Confluence 6 整合到其他数据库
  15. Java 创建一个窗口,使其启动时位于屏幕中间
  16. 在vue2.x项目中怎么引入Element UI
  17. centos 支持安装libsodium
  18. day31-软件开发规范
  19. js如何用json 读取C#的Dictionary
  20. 新版Java为什么要修改substring的实现

热门文章

  1. python 几个常用自定义函数在dataframe上的应用
  2. SourceTree 关于 .gitignore使用/下载
  3. LitJson(读Exce文件写入到json文件):
  4. 牛客网Java刷题知识点之什么是进程、什么是线程、什么是多线程、多线程的好处和弊端、多线程的创建方式、JVM中的多线程解析、多线程运行图解
  5. Java的ThreadContext类加载器
  6. crypto-js遇到的坑
  7. 微信小程序电商实战-商品列表流式布局
  8. Cg shadow of sphere
  9. Android开发基础
  10. python模块介绍和 import本质