享元模式(英语:Flyweight Pattern)是一种软件设计模式。它使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。
定义
享元模式(FlyWeight),运用共享技术有效的支持大量细粒度的对象。
结构
两个状态
内蕴状态存储在享元内部,不会随环境的改变而有所不同,是可以共享的。
外蕴状态是不可以共享的,它随环境的改变而改变的,因此外蕴状态是由客户端来保持(因为环境的变化是由客户端引起的)。
UML结构图
(1) 抽象享元角色:为具体享元角色规定了必须实现的方法,而外蕴状态就是以参数的形式通过此方法传入。在Java中可以由抽象类、接口来担当。
(2) 具体享元角色:实现抽象角色规定的方法。如果存在内蕴状态,就负责为内蕴状态提供存储空间。
(3) 享元工厂角色:负责创建和管理享元角色。要想达到共享的目的,这个角色的实现是关键!
(4) 客户端角色:维护对所有享元对象的引用,而且还需要存储对应的外蕴状态。
使用场景
需要大量细粒度对象
这些对象的外部状态不多
按照内部状态分成几个组,每一个组都仅用一个蝇量对象代替
优缺点
优点:
- 减少运行时的对象实例个数,节省创建开销和内存
- 将许多“虚拟”对象的状态集中管理
缺点:
- 系统设计更加复杂
- 需要专门维护对象的外部状态
示例代码:
public abstract class Plant {
public Plant() {
}
public abstract void display(int xCoord, int yCoord, int age);
}
public class Grass extends Plant {
@Override
public void display(int xCoord, int yCoord, int age) {
// TODO Auto-generated method stub
// System.out.print("Grass x");
}
}
public class Tree extends Plant {
@Override
public void display(int xCoord, int yCoord, int age) {
// TODO Auto-generated method stub
// System.out.print("Tree x");
}
}
import java.util.HashMap;
public class PlantFactory {
private HashMap<Integer, Plant> plantMap = new HashMap<Integer, Plant>();
public PlantFactory() {
}
public Plant getPlant(int type) {
if (!plantMap.containsKey(type)) {
switch (type) {
case 0:
plantMap.put(0, new Tree());
break;
case 1:
plantMap.put(1, new Grass());
break;
}
}
return plantMap.get(type);
}
}
public class PlantManager {
private int length = 10000000;
private int[] xArray = new int[length], yArray = new int[length],
AgeArray = new int[length], typeArray = new int[length];
private PlantFactory mPlantFactory;
public PlantManager() {
mPlantFactory=new PlantFactory();
for (int i = 0; i < length; i++) {
xArray[i] = (int) (Math.random() * length);
yArray[i] = (int) (Math.random() * length);
AgeArray[i] = (int) (Math.random() * length) % 5;
typeArray[i]= (int) (Math.random() * length) % 2;
}
}
public void displayTrees() {
for (int i = 0; i < length; i++) {
mPlantFactory.getPlant(typeArray[i]).display(xArray[i], yArray[i], AgeArray[i]);
}
}
}
public class PlantManager {
private int length = 10000000;
private int[] xArray = new int[length], yArray = new int[length],
AgeArray = new int[length], typeArray = new int[length];
private PlantFactory mPlantFactory;
public PlantManager() {
mPlantFactory=new PlantFactory();
for (int i = 0; i < length; i++) {
xArray[i] = (int) (Math.random() * length);
yArray[i] = (int) (Math.random() * length);
AgeArray[i] = (int) (Math.random() * length) % 5;
typeArray[i]= (int) (Math.random() * length) % 2;
}
}
public void displayTrees() {
for (int i = 0; i < length; i++) {
mPlantFactory.getPlant(typeArray[i]).display(xArray[i], yArray[i], AgeArray[i]);
}
}
}