前言
在说享元模式之前, 你一定见到过这样的面试题
- public class Test {
- public static void main(String[] args) {
- Integer a=Integer.valueOf(127);
- Integer b=new Integer(127);
- System.out.println(a==b);
- int c=127;
- System.out.println(a==c);
- System.out.println(b==c);
- }
- }
问你输出结果是什么? 有些人可能一下就看出了答案是什么, 有些人可能不是特别清楚. 那么一起看下面的文章. 我想你很快就能知晓.
一, 享元模式定义
提供了减少对象数量从而改善应用所需的对象结构方式, 使用共享技术有效地支持大量细粒度的对象.
二, 适用场景
常用于系统底层开发, 以便解决系统的性能问题. 像数据库连接池, 里面都是创建好的连接对象, 在这些连接对象中有我们需要的则直接拿来用, 避免重新创建. 如果没有我们需要的, 则创建一个.
在一个系统中有大量相似对象, 需要缓冲池的场景. 不需要一直创建一个新的对象, 可以直接从缓冲池里拿. 这样可以降低系统内存, 同时提高效率.
三, 内部状态与外部状态
内部状态:
在享元模式内部, 不随外界的改变而改变. 比如说 Integer 类中的 MIN_VALUE 和 MAX_VALUE 两个值, 无论外部传什么值. 都不会改变这两个值.
外部状态:
这就很好理解了, 就是随外部的改变而改变的状态. 比如说 Integer 类中的 value 值.
四, Integer 中的享元模式
经过上面的介绍, 你肯定大概了解了享元模式的概念. 那么我们来看看 Integer 中的享元模式具体是怎么样的吧.
- public final class Integer extends Number implements Comparable<Integer> {
- public static Integer valueOf(int i) {
- if (i>= IntegerCache.low && i <= IntegerCache.high)
- return IntegerCache.cache[i + (-IntegerCache.low)];
- return new Integer(i);
- }
- private final int value;
- public Integer(int value) {
- this.value = value;
- }
- }
上面是我简化了的 Integer 类. 平常在使用 Integer 类的时候. 你是否思考过用 valueOf 还是用 new 创建 Integer 对象. 看完源码就会发现在 valueOf 这个方法中它会先判断传进去的值是否在 IntegerCache 中, 如果不在就创建新的对象, 在就直接返回缓存池里的对象. 这个 valueOf 方法就用到享元模式. 它将 - 128 到 127 的 Integer 对象先在缓存池里创建好, 等我们需要的时候直接返回即可. 所以在 - 128 到 127 中的数值我们用 valueOf 创建会比 new 更快. 如果你还想继续往里钻研, 可以去看看 IntegerCache 如何实现. 在这里我们主要说设计模式. 看接下来的一个测试代码及内存分析.
这里就可以很清晰的看出来 a 和 b 的内存不相等. 结果当然是 false. 回到我们的设计模式上来, 在实际的场景中我们更多的是完成缓冲池的创建, 来达到缓冲池对象里面复用的功能. 就像下面这种情况, 尽管我定义了两个不同的对象, 但实际上我指向的是同一块内存地址, 这样就减少了系统内存, 并且使系统的响应速度更快.
五, 总结
在享元模式里我们要理解享元,"享" 就表示共享,"元" 表示对象. 当我们频繁需要这个对象的时候, 我们考虑 new, 考虑 clone 等等这些方法. 当然这些方法实际上用的场景和这个不一样. 看上面的内存分析就能知道, 我们频繁需要相同的一个范围内的对象去做某件事情, 我们还需要重新创建对象就会有两个缺点: 第一就是内存浪费, 第二就是性能稍慢, 特别是我这个对象 new 起来需要响应的时间很长的时候. 这时候考虑用享元模式来先创建一个缓冲池会更好. 这个缓冲池可以放在容器中进行存储, 当我们需要的时候直接拿出来用即可. 一次创建, 多次使用.
在这里多说一点就是当 int 类型和 Integer 比较的时候会自动的拆箱也就是只比较里面的值大小是否相等, 所以上面的答案就是 false,true,true.
来源: https://www.cnblogs.com/Cubemen/p/10666164.html