|
享元模式(Flyweight Pattern),运用共享技能有效支撑大量细粒度的对象。
主要目的是减少系统中大量重复的细粒度对象,降低系统运行时的代价,提高系统运行速度。
享元对象有内部状态与外部状态:
内部状态,在享元对象的内部并且不会随环境改动而改动的共享部分。
外部状态,随环境改动而改动的,不能够共享的状态。
项目背景:该项目是一款以架空战国时代为背景的策略型网络游戏。玩家可以在【地图】上创建【城池】,刷怪等操作。
为了提升在线人数,【地图】需要足够大,能容纳更多的人创建【城池】。【地图】是用坐标(x,y)点来标识的——我管它叫【坐标点】,【坐标点】有坐标、【城池】Id(如果创建了【城池】)、是否可创建【城池】等属性。
如果每个【坐标点】创建一个对象,这样的开销是很惊人的,以横坐标1594,纵坐标1594为例,1594乘以1594=2540836,2百多万个对象创建在内存中,这样的系统开销是很大的,如果再做循环等操作,可以想象想性能是怎么样的?(顺便多说一句,据我所知,很多网游地图确实是这样做的!)。
因此,享元模式(Flyweight Pattern)在这里运用是非常非常的重要。
分析设计:仔细分析,【坐标点】有两类,一类是没有创建【城池】的——我管它叫【空坐标点】,另一类是已经创建【城池】的——我管它叫【实坐标点】。
【空坐标点】除了坐标是“外部状态”(随环境改动而改动的),其他属性是“内部状态”,可以共享。【实坐标点】的大部分属性是“外部状态”。
Java代码实现:
/**
* 抽象地图坐标点
*
* @author 董有红
* @version 1.0, 2009/03/07
*/
public abstract class MapCell {
/** 横坐标 */
protected int posx;
/** 纵坐标 */
protected int posy;
/** 城池Id */
protected int castleId;
/** 其他属性省略 */
……
/**
* 设置坐标方法,子类不用过载,可直接使用
*
* @param posx 横坐标
* @param posy 纵坐标
*/
public void setPos(int posx, int posy) {
this.posx = posx;
this.posy = posy;
}
/**
* 抽象方法,判断该坐标点是否可用
*
* @return 判断的结果
*/
public abstract boolean isAvail();
// 其他方法,省略……
}
/**
* 空坐标点
*
* @author 董有红
* @version 1.0, 2009/03/07
*/
public class EmptyMapCell extends MapCell {
/**
* 根据城池等级不同,占用的坐标点个数不同,
* 需要判断该坐标点是否可用
*
* @return 判断的结果
*/
public boolean isAvail() {
// 代码省略……
}
// 其他方法,省略……
}
/**
* 实坐标点
*
* @author 董有红
* @version 1.0, 2009/03/07
*/
public class SolidMapCell extends MapCell {
/**
* 该坐标点已经被城池占用,不可用
*
* @return 判断的结果
*/
public boolean isAvail() {
return false;
}
// 其他方法,省略……
}
import java.util.*;
/**
* 地图实例创建工厂,采用单例模式
*
* @author 董有红
* @version 1.0, 2009/03/07
*/
public class MapCellFactory {
/** 持有地图实例创建工厂句柄 */
private static MapCellFactory factory;
/** 持有地图坐标的容器 */
private Map mapCells;
/**
* 私有构造器
*/
private MapCellFactory() {
mapCells = new HashMap();
EmptyMapCell emptyMapCell = new EmptyMapCell();
mapCells.push("emptyMapCell", emptyMapCell);
SolidMapCell solidMapCell = new SolidMapCell();
mapCells.push("emptyMapCell", emptyMapCell);
}
/**
* 创建实例工厂,静态方法
*
* @return 返回工厂实例
*/
public static MapCellFactory createMapCellFactory() {
if (factory == null)
factory = new MapCellFactory();
return factory;
}
/**
* 取得地图坐标
*
* @param key 建值
*
* @return 地图坐标
*/
public MapCell getMapCell(String key) {
return (MapCell)mapCells.get(key);
}
// 其他方法,省略……
}
|
|