设计模式18-蝇量(享元)模式

176 阅读2分钟

1.场景问题解决

1.1 场景描述

1.2 OO设计

1.3 需求变动

1.4 带来问题

2.用设计模式改进

2.1 分析

大量的微小的对象,对象属性拆开-内部属性和外部属性拆开;

比如树对象,普通设计为:有一个集合存储树对象,每个对象有其对应的横坐标,纵坐标,及年龄 .

而蝇量模式为: 多个集合(每个集合长度一样),第一个集合保存所有虚拟树对象,第二个保存所有树的横坐标,第三个保存树的所有纵坐标,第四个保存所有树的年龄. 在需要的情况下在将每个集合中的值拿出来组合树对象.
18蝇量模式-2

2.2 重新设计

2.3 源码

  • oo模式,Tree(树对象),TreesTest(树集合),OOTest(测试类)
public class Tree {
	private int xCoord, yCoord, age;

	public Tree(int xCoord, int yCoord, int age) {
		this.xCoord = xCoord;
		this.yCoord = yCoord;
		this.age = age;
	}

	public void display() {
		// System.out.print("x");
	}
}


public class TreesTest {
	private int length = 10000000;
	private Tree[] treelst = new Tree[length];

	public TreesTest() {
		for (int i = 0; i < length; i++) {
			treelst[i] = new Tree((int) (Math.random() * length),
					(int) (Math.random() * length),
					(int) (Math.random() * length) % 5);
		}
	}

	public void display() {
		for (int i = 0, len = treelst.length; i < len; i++) {
			treelst[i].display();
		}
	}
}



public class OOTest {
	public static void main(String[] args) {
		showMemInfo();
		TreesTest mTreesTest;
		mTreesTest = new TreesTest();

		showMemInfo();
		mTreesTest.display();
		showMemInfo();
	}

	public static void showMemInfo() {
		// 最大内存:
		long max = Runtime.getRuntime().maxMemory();
		// 分配内存:
		long total = Runtime.getRuntime().totalMemory();
		// 已分配内存中的剩余空间 :
		long free = Runtime.getRuntime().freeMemory();
		// 已占用的内存:
		long used = total - free;

		System.out.println("最大内存 = " + max);
		System.out.println("已分配内存 = " + total);
		System.out.println("已分配内存中的剩余空间 = " + free);
		System.out.println("已用内存 = " + used);
		System.out.println("时间 = " + System.currentTimeMillis());
		System.out.println("");
	}
}
  • 蝇量模式,TreeFlyWeight(蝇量树),TreeManager(蝇量树管理),FlyWeightTest(测试类)
public class TreeFlyWeight {
	public TreeFlyWeight() {
	}

	public void display(int xCoord, int yCoord, int age) {
		// System.out.print("x");
	}
}



public class TreeManager {
	private int length = 10000000;
	int[] xArray = new int[length],
		  yArray = new int[length],
		  AgeArray = new int[length];

	private TreeFlyWeight mTreeFlyWeight;

	public TreeManager() {
		mTreeFlyWeight = new TreeFlyWeight();
		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;
		}
	}

	public void displayTrees() {
		for (int i = 0; i < length; i++) {
			mTreeFlyWeight.display(xArray[i], yArray[i], AgeArray[i]);
		}
	}
}



public class FlyWeightTest {
	public static void main(String[] args) {
			showMemInfo();
		TreeManager mTreeManager;
		mTreeManager = new TreeManager();
			showMemInfo();
		mTreeManager.displayTrees();
			showMemInfo();
	}

	public static void showMemInfo() {
		// 已分配内存中的剩余空间 :
		long free = Runtime.getRuntime().freeMemory();
		// 分配内存:
		long total = Runtime.getRuntime().totalMemory();
		// 最大内存:
		long max = Runtime.getRuntime().maxMemory();
		// 已占用的内存:

		long used = total - free;

		System.out.println("最大内存 = " + max);
		System.out.println("已分配内存 = " + total);
		System.out.println("已分配内存中的剩余空间 = " + free);
		System.out.println("已用内存 = " + used);
		System.out.println("时间 = " + System.currentTimeMillis());
		System.out.println("");
	}
}

  • 支持多种植物模式,Plant(植物抽象类),Tree(蝇量树),Grass(蝇量草),PlantFactory(保存植物厂房),PlantManager(植物管理器),FlyWeight2Test(测试类)
public abstract class Plant {
	public Plant() {
	}
	public abstract void display(int xCoord, int yCoord, int age);
}

public class Tree extends Plant {
	@Override
	public void display(int xCoord, int yCoord, int age) {
		// System.out.print("Tree x");
	}
}

public class Grass extends Plant {
	@Override
	public void display(int xCoord, int yCoord, int age) {
		// System.out.print("Grass x");
	}
}


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 FlyWeight2Test {

	public static void main(String[] args) {
		showMemInfo();
		PlantManager mPlantManager;
		mPlantManager = new PlantManager();
		showMemInfo();
		mPlantManager.displayTrees();
		showMemInfo();
	}

	public static void showMemInfo() {
		// 已分配内存中的剩余空间 :
		long free = Runtime.getRuntime().freeMemory();
		// 分配内存:
		long total = Runtime.getRuntime().totalMemory();
		// 最大内存:
		long max = Runtime.getRuntime().maxMemory();
		// 已占用的内存:

		long used = total - free;

		System.out.println("最大内存 = " + max);
		System.out.println("已分配内存 = " + total);
		System.out.println("已分配内存中的剩余空间 = " + free);
		System.out.println("已用内存 = " + used);
		System.out.println("时间 = " + System.currentTimeMillis());
		System.out.println("");
	}
}

3.设计模式总结

3.1 定义

**蝇量模式:**通过共享的方式高效地支持大量细粒度的对象。

3.2 分析思路

18蝇量模式-1

3.3 蝇量模式优缺点

  • 优点:
    • 减少运行时的对象实例个数,节省创建开销和内存
    • 将许多“虚拟”对象的状态集中管理
  • 缺点:
    • 系统设计更加复杂
    • 需要专门维护对象的外部状态

4. 设计模式使用场景及注意

4.1 适用场合:

  • 需要大量细粒度对象
  • 这些对象的外部状态不多
  • 按照内部状态分成几个组,每一个组都仅用一个蝇量对象代替

5.参考文章

内容总计于HeadFirst设计模式及相关视频