java 开发模式之十八 :蝇量模式(享元模式)

来源:互联网 发布:网络推广代运营公司 编辑:程序博客网 时间:2024/04/30 11:40

原理或定義

能做到共享的关键是区分内蕴状态(Internal State)和外蕴状态(External State).
一个内蕴状态是存储在享元对象内部的,并且不会随环境改变而有所不同.因此,一个享元可以具有内蕴状态并可以共享 .一个外蕴状态是随环境改变而改变的,不可以共享状态.享元对象的外蕴状态必须由客户端保存, 并在享元对象被创建之后在需要使用的时候再传到享元对象内部.

单纯享元模式结构

抽象享元(Flyweight)角色 :给出一个抽象接口,以规定出所有具体享元角色需要实现的方法。
具体享元(ConcreteFlyweight)角色:实现抽象享元角色所规定出的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。
享元工厂(FlyweightFactory)角色 :本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象调用一个享元对象的时候,享元工厂角色会检查系统中是否已经有一个符合要求的享元对象。如果已经有了,享元工厂角色就应当提供这个已有的享元对象;如果系统中没有一个适当的享元对象的话,享元工厂角色就应当创建一个合适的享元对象

复合享元模式结构

其他角色同上。

复合享元(ConcreteCompositeFlyweight)角色 :复合享元角色所代表的对象是不可以共享的,但是一个复合享元对象可以分解成为多个本身是单纯享元对象的组合。复合享元角色又称作不可共享的享元对象。

類圖

案例与代码

景观设计软件项目遇到的问题:
树:XY坐标,树的大小,外观,需要很多树
例如10000000棵树


一般设计方案:


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");}}


一般会直接生成10000000个对象。但是生成10000000个对象是需要很多内存和CPU的开销的。


蝇量模式设计方案:

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 MainTest {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("");}}

需求变更:景观项目里需要增加大量的草对象

抽象享元(Flyweight)角色 

public abstract class Plant {public Plant() {}public abstract void display(int xCoord, int yCoord, int age);}


具体享元(ConcreteFlyweight)角色
public class Grass extends Plant {@Overridepublic void display(int xCoord, int yCoord, int age) {// TODO Auto-generated method stub// System.out.print("Grass x");}}
public class Tree extends Plant {@Overridepublic void display(int xCoord, int yCoord, int age) {// TODO Auto-generated method stub// System.out.print("Tree x");}}

享元工厂(FlyweightFactory)角色 

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 MainTest {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("");}}

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



使用場景

1.一个应用程序使用了大量的对象。
2 完全由于使用大量的对象,造成很大的存储开销。
3 对象的大多数状态都可以变为外部状态。
4 如果删除对象以外的状态那么可以用相对较少的共享对象取代很多组对象。
5 应用程序不依赖于对象标识

優缺點

主要优点有:

1.减少运行时的对象实例个数,节省创建开销和内存
2.将许多“虚拟”对象的状态集中管理

主要缺点有:

1.系统设计更加复杂

2.需要专门维护对象的外部状态


阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 做月子在家无聊怎么办 坐月子太无聊了怎么办 做小月子无聊怎么办 老公去世结婚证怎么办 上班被领导骂怎么办 多次移植不着床怎么办 想当兵学历不够怎么办 如果当兵被欺负怎么办 当兵家人被欺负怎么办 媳妇老想睡觉怎么办 分手初期很难受怎么办 士官证掉了怎么办 不知道激活锁怎么办 回头率太高了怎么办 当兵背后有纹身怎么办 前任欠我钱怎么办 眼镜边框氧化了怎么办 眼镜片有502胶水怎么办 眼镜镜片刮了怎么办 太阳镜上的划痕怎么办 新眼镜片有划痕怎么办 屋里有狗臭味怎么办 高考戴眼镜的怎么办 钱花了心疼怎么办 花了冤枉钱心疼怎么办 乱花钱后很内疚怎么办 乱花钱后很后悔怎么办 不想养狗了怎么办 小狗狗身上有味怎么办 狗宝宝有点拉稀怎么办 气味大怎么办小金毛 养宠物后悔了怎么办 养的狗狗不想要怎么办 gta5出货断网怎么办 ps4gta5改装王bug怎么办 宠物狗不想养了怎么办 吃药流产出血多怎么办 狗狗得了皮炎怎么办 药流第三天没血怎么办 药流出血量大怎么办 车行168被骗了怎么办