GoF设计模式之十一 Flyweight- -

来源:百度文库 编辑:神马文学网 时间:2024/04/28 11:21:20
B6) Flyweight(享元模式)
定义:使用共享来高效的支持大量的细颗粒对象。
似乎不太常用的一个模式,因为对于要求可能严格了一点:大量的细颗粒对象,真正运用到这个层次上的机会应该不会太多。享元模式就是将大量对象实例中相同的部分提取出来,形成一个原型,这部分称为intrinsic(内部状态),是不变的,而会因外界条件而改变的部分称为extrinsic(外部状态)。那每次需要一个新的对象实例时候,就从享元共享池(pool)中得到内部状态即共享的原型,再根据外部条件,生成外部状态,这样如果是大规模数量的对象,就可以节省很多内存空间。是不是很像文件压缩技术?那就以压缩图像文件的例子来说明一下。首先是BMP文件类:
public class BMPFile {
private FileInfo info;
private Map pixelMap;
public Pixel getPixel(Position pos) {
return pixelMap.get(pos);
}
public void setPixel(Position pos, RGB color) {
Pixel pixel = new Pixel(pos, color);
pixelMap.put(pos, pixel);
}
}
FileInfo包括文件名、大小、日期等等,这暂时不考虑,因为对于享元模式,图片上的成千上万甚至上百万千万的像素(pixel)才是需要考虑的大量的细颗粒对象。像素(pixel)类,包含颜色和坐标,假设一个256色的BMP文件,那么颜色是固定的256种,就是内部状态,而坐标却会因为图片的样子和大小而变化,就是外部状态。如下:
public class Pixel {
private RGB color;
private Position pos;
public Pixel(Position pos, RGB color) {
this.pos = pos;
this.color = color;
}
}
现在开始压缩,假设分析某个BMP文件后发现,这个BMP共包含两种颜色,黑(RGB:000000)和白(RGB:FFFFFF),图片大小为100x100。那么,这个BMP文件大小为10000个像素x每个像素的大小(假设为12个字节,颜色占用6个,坐标占用6个)+文件信息段(假设为500个字节),共计120500字节。转换成压缩格式,使用享元共享池
public class PixelPool {
private Map pool = new Hashmap();
public Pixel getPixel(RGB color) {
Pixel pixel = pool.get(color);
if (pixel == null) {
pixel = new Pixel(null, color);
pool.put(color, pixel);
}
return pixel;
}
}
那么,得到的新的压缩后的文件为:
public class CompressedBMPFile extends BMPFile {
private PixelPool pool = new PixelPool();
public void setPixel(Position pos, RGB color) {
Pixel pixel = pool.getPixel(color);
pixel.setPosition(position);
pixelMap.put(pos, pixel);
}
}
重新来计算一下新的压缩后的文件大小,两个颜色的像素占用2x6个字节+坐标占用字节10000x6+文件信息500字节,大约是60512字节,小了一半。就算是256色的BMP,总共的大小也只有256x6+10000x6+500=62036字节。当然,纪录用的享元池可能还有部分开销,但总体来说,节省了很大的空间,而且通过pool得到已有的pixel对象,不用每次创建新的对象,也是非常节省系统资源的。