享元模式(Flyweight Pattern),是对象池的一种体现,也是 GoF 的 23 种设计模式中的一种结构型设计模式。 享元模式 主要用于减少创建对象的数量,以减少内存占用和提高性能。它提供了减少对象数量从而改善应用所需的对象结构的方式。 享元模式 尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。 ~ 本篇内容包括:关于享元模式、享元模式 Demo
享元模式(Flyweight Pattern),是对象池的一种体现,也是 GoF 的 23 种设计模式中的一种结构型设计模式。
享元模式 主要用于减少创建对象的数量,以减少内存占用和提高性能。它提供了减少对象数量从而改善应用所需的对象结构的方式。
享元模式 尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。
享元模式主要包含四种角色:
当系统中多处需要同一组信息时,可以吧这些信息封装到一个对象中,然后对该对象进行缓存,这样,一个对象就可以提供给多处需要使用的地方,避免大量同一对象多次创建,消耗大量内存空间。 享元模式其实就是工厂模式的一个改进机制,享元模式同样要求创建一个或一组对象,并且就是通过工厂方法生成对象的,只不过享元模式中为工厂方法增加了缓存这一功能。主要总结为以下应用场景:
在生活中的享元模式也很常见,比如中介机构的房源共享,再比如全国社保联网。
在 Java 中最直观的享元模式就是在 Boolean,Byte,Integer,Long,Character 这些包装类中,他们都提供了valueOf()方法。
比如:Long 的 valueOf() 方法会缓存数值 -127~128 之间的 Long 对象,在这个范围之间就会直接在这个里面去取,大于这个范围才会去 new Long 对象
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
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);
}
}
Byte,Short,Long 的范围是 -127~128 之间。
Character 是 0~127 之间。
Integer 是 -127~128 之间,最小值不能改变,但是最大值可以通过虚拟机参数进行改变。-Djava.long.Intger.IntegerCache.high 来改变
Boolean 缓存了 TRUE 和 FALSE
# 享元模式的优点:
# 享元模式的缺点:
俄罗斯方块有不同的形状,我们可以对这些形状向上抽取出 AbstractBox,用来定义共性的属性和行为。
接下来就是定义不同的形状了,IBox类、LBox类、TBox类等。
提供了一个工厂类(BoxFactory),用来管理享元对象(也就是 AbstractBox 子类对象),该工厂类对象只需要一个,所以可以使用单例模式。并给工厂类提供一个获取形状的方法。
# AbstractBox 抽象享元角色
public abstract class AbstractBox {
public abstract String getShape();
public void display(String color) {
System.out.println("方块形状:" + this.getShape() + " 颜色:" + color);
}
}
# IBox/LBox/TBox 具体享元角色
public class IBox extends AbstractBox {
@Override
public String getShape() {
return "I";
}
}
public class LBox extends AbstractBox {
@Override
public String getShape() {
return "L";
}
}
public class TBox extends AbstractBox {
@Override
public String getShape() {
return "T";
}
}
# BoxFactory 享元工厂
public class BoxFactory {
private static HashMap<String, AbstractBox> map;
private BoxFactory() {
map = new HashMap<String, AbstractBox>();
AbstractBox iBox = new IBox();
AbstractBox lBox = new LBox();
AbstractBox oBox = new OBox();
map.put("I", iBox);
map.put("L", lBox);
map.put("O", oBox);
}
public static final BoxFactory getInstance() {
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder {
private static final BoxFactory INSTANCE = new BoxFactory();
}
public AbstractBox getBox(String key) {
return map.get(key);
}
}