享元模式又称蝇量模式,通过内部维护一个对象池防止相同属性对象的重复创建,节约内存开支
与单例模式区别:
个人理解享元模式最主要将对象区分为内部状态(IntrinsicState)与外部状态(ExtrinsicState),内部状态是区分是否为同一对象的唯一指标。
(类似于购买从南京到苏州的高铁票,起始地、目的地、车次、座位号、时间等都是车票的内部状态,而持有者则是外部状态,你购买到了就是你的,若退票则会改变外部状态被另一个人持有,而票是同一张票。)
- 单例模式只创建唯一一个实例,享元模式根据内部状态不同可创建多个实例
- 单例模式是在类级别做控制,享元是在对象级别,实际为对象的缓存
/**
* 角色(FLyweight 抽象享元)
*/
public abstract class SqlConnection {
protected String name;
public SqlConnection(String name){
this.name = name;
}
public abstract void operation(User user);
}
/**
* 角色(concreteFlyweight)
*/
public class MySqlConnection extends SqlConnection{
public MySqlConnection(String name) {
super(name);
}
@Override
// 外部状态(user)通过方法传入
public void operation(User user) {
System.out.println("ExtrinsicState : " + user.getName());
System.out.println("IntrinsicState : " + this.name);
}
}
/**
* 角色(unsharedConcreteFlyweight)
*/
public class User {
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 角色(flyweightFactory)
*/
public class ConnectionFactory {
private Map<String, SqlConnection> connectionPool = new HashMap<>();
public SqlConnection getSqlConnection(String name){
SqlConnection sqlConnection = connectionPool.get(name);
if(sqlConnection == null){
sqlConnection = new MySqlConnection(name);
connectionPool.put(name, sqlConnection);
}
System.out.println("total : " + connectionPool.size());
return sqlConnection;
}
}
测试类
public class Test {
public static void main(String[] args) {
ConnectionFactory factory = new ConnectionFactory();
SqlConnection sqlConnection1 = factory.getSqlConnection("connection1");
SqlConnection sqlConnection2 = factory.getSqlConnection("connection2");
User user1 = new User();
user1.setName("me");
sqlConnection1.operation(user1);
User user2 = new User();
user2.setName("u");
sqlConnection1.operation(user2);
}
}
结果
jdk源码应用——Integer.valueOf
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
可以看到在-128——127之间的数是在整型缓存中直接取出的(享元模式中最重要的享元工厂)