享元模式(Flyweight)/ 轻量级模式

共享细粒度对象,不必为每个访问者单独创建一个对象,以此降低内存消耗。

内部状态、外部状态

享元模式将对象的状态分为内部状态、外部状态。内部状态即不变,外部状态即变化。通过共享不变的部分,达到减少对象数量并节约内存。

内部状态:比如连接池中的配置,这些配置信息是不会变化的。

外部状态:比如连接池中的连接,各个连接有不同的状态,有些受状态影响可被回收。
一般配合工厂模式使用,如果缓存中有,则直接返回,如果没有则新建一个对象并放在缓存中,最后返回。

应用场景

  1. 将一组数据封装在对象中,然后缓存该对象,并提供给多出使用。
  2. 常用于系统底层开发,以解决性能问题。
  3. 系统有大量相似对象、需要缓冲池的场景。

比如:
1) 房产中介房源信息共享。
2) 全国社保联网,数据共享。
3) String – 常量
4) Integer Integer.valuesOf // -128~127 放在cache中

代码实现

map 中存储,外部获取对象时,map中有则直接返回
public class Factory {
   private static final HashMap<String, Persion> map = new HashMap<>();

   public Persion get(String id){
      Object obj = map.get(id);	// 先从map中获取,没有再new
      if(obj == null){
         return  new Persion("qq", 1);
      }
      return (Persion) obj;
   }
}
String
public class StringTest {
  public static void main(String[] args) {
    String s1 = "hello";
    String s2 = "hello";
    String s3 = "he" + "llo";
    String s4 = "he";
    String s5 = "llo";
    String s6 = s4 + s5;
    String s7 = new String("hello");
    System.out.println("s1 == s2 :"+(s1 == s2)); 	// 同一个常量
    System.out.println("s1 == s3 :"+(s1 == s3));	// 编译时"he" + "llo"优化成"hello"
    System.out.println("s1 == s6 :"+(s1 == s6)); 	// 编译时s4 s5是引用(类似分派调用)
    System.out.println("s1 == s7 :"+(s1 == s7)); 	// new 新的地址引用
  }
}

输出结果:
s1 == s2 :true
s1 == s3 :true
s1 == s6 :false
s1 == s7 :false

总结:

  1. "hello"为常量,“he” + “llo"编译时优化成"hello”,所以s1、s2、s3是相等的。
  2. new 之后,就会生成新的地址引用,就不相等了。
  3. s4 + s5是引用,跟"he" + "llo"不同。
Integer
public class IntegerTest {
  public static void main(String[] args) {
    int i1 = 128;
    Integer i2 = new Integer(128);
    Integer i22 = new Integer(128);
    System.out.println("i1 == i2 : " + (i1 == i2));	 // int 等于 Integer
    System.out.println("i2 == i22 : " + (i2 == i22)); // new Integer 不等于 new Integer
    Integer i3 = Integer.valueOf(127);
    Integer i4 = Integer.valueOf(127);
    System.out.println("i3 == i4 : " + (i3 == i4));	 // valueOf源码中,-128 - 127 是从cache中获取的
    Integer i5 = Integer.valueOf(128);
    Integer i6 = Integer.valueOf(128);
    System.out.println("i5 == i6 : " + (i5 == i6));
  }
}

输出结果
i1 == i2 : true
i2 == i22 : false
i3 == i4 : true
i5 == i6 : false

总结:

  1. int 等于 Integer
  2. new Integer 不等于 new Integer
  3. valueOf源码中,-128 - 127 是从cache中获取的

源码中的应用

Integer.valueOf()

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

Long.LongCache{}

private static class LongCache {
    private LongCache(){}

    static final Long cache[] = new Long[-(-128) + 127 + 1];

    static {
        for(int i = 0; i < cache.length; i++)
            cache[i] = new Long(i - 128);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值