享元模式(Flyweight)/ 轻量级模式
内部状态、外部状态应用场景代码实现map 中存储,外部获取对象时,map中有则直接返回StringInteger
源码中的应用Integer.valueOf()Long.LongCache{}
共享细粒度对象,不必为每个访问者单独创建一个对象,以此降低内存消耗。
内部状态、外部状态
享元模式将对象的状态分为内部状态、外部状态。内部状态即不变,外部状态即变化。通过共享不变的部分,达到减少对象数量并节约内存。
内部状态:比如连接池中的配置,这些配置信息是不会变化的。
外部状态:比如连接池中的连接,各个连接有不同的状态,有些受状态影响可被回收。 一般配合工厂模式使用,如果缓存中有,则直接返回,如果没有则新建一个对象并放在缓存中,最后返回。
应用场景
将一组数据封装在对象中,然后缓存该对象,并提供给多出使用。常用于系统底层开发,以解决性能问题。系统有大量相似对象、需要缓冲池的场景。
比如: 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
);
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
));
System
.out
.println("s1 == s6 :"+(s1
== s6
));
System
.out
.println("s1 == s7 :"+(s1
== s7
));
}
}
输出结果: s1 == s2 :true s1 == s3 :true s1 == s6 :false s1 == s7 :false
总结:
"hello"为常量,“he” + “llo"编译时优化成"hello”,所以s1、s2、s3是相等的。new 之后,就会生成新的地址引用,就不相等了。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
));
System
.out
.println("i2 == i22 : " + (i2
== i22
));
Integer i3
= Integer
.valueOf(127);
Integer i4
= Integer
.valueOf(127);
System
.out
.println("i3 == i4 : " + (i3
== i4
));
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
总结:
int 等于 Integernew Integer 不等于 new IntegervalueOf源码中,-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);
}
}