小话设计模式(十一)享元模式
来源:互联网 发布:懒人听书软件 编辑:程序博客网 时间:2024/06/05 18:38
享元(Fly Weight直译作蝇量)模式运用共享技术有效的支持大量细颗粒的对象。
一般使用享元模式的时候要满足下列所有情况:
1、 一个应用程序使用了大量的对象。
2、 完全由于使用大量的对象,造成了很大的存储开销。
3、 对象的大多数状态都可以变外外部状态。
4、 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
5、 应用程序不依赖与对象标识。
举个例子
一个RPG游戏,怪兽或者英雄都可以改变等级,改变等级之后,二者的攻击力都会发生变化。我们将等级数据(每一级对应的攻击力)存放在本地数据文件里。当我们需要创建一个对象的时候,就要获取这些等级数据。
游戏里的等级数据定义如下:
public abstract class LevelData{protected virtual void LoadFromFile (string filePath){//TODO:}public abstract int GetAttack (ClientData data);}
这些数据都是从本地数据文件中读取出来的,这些数据对于每个怪兽都是一样的,所以是共享数据。而且,这些数据是不会变的,除非修改数据文件。
这里提供了一个GetAttack的公开方法,用于获取(怪兽、英雄)攻击力
怪兽等级数据:
public class MonsterLevelData : LevelData{public int ID { get; private set;}public MonsterLevelData(int monID){ID = monID;//For different heroes, load different files.LoadFromFile (monID.ToString());}private List<int> _levelAttackList = new List<int> ();//Loaded in the method LoadFromFileprotected override void LoadFromFile(string filePath){base.LoadFromFile (filePath);//TESTfor (int i = 1; i <= 10; i++) {_levelAttackList.Add (i * 10);}}public override int GetAttack (ClientData data){int lv = data.Level;lv = System.Math.Min (System.Math.Max (lv, 1), 10);int attack = _levelAttackList [lv - 1];return attack + data.AttackPlus;}}
接着,我们定义了怪兽的类,包含了怪兽的等级和攻击力加成。在创建怪兽对象的时候,我们就可以根据这两个值的不同,获取不同的攻击力。因为是可变的,所以被定义为外部数据:
public class ClientData{public int Level {get;set;}public int AttackPlus { get; set;}}
那么如何共享对象呢?这里需要建立一个享元工厂:
public static class LevelDataFactory{public static Dictionary<int, LevelData> _monsterLevelData = new Dictionary<int, LevelData>();public static LevelData GetMonsterLevelData(int monID){if (!_monsterLevelData.ContainsKey (monID)) {_monsterLevelData [monID] = new MonsterLevelData (monID);}return _monsterLevelData [monID];}}
因为我们希望相同的怪兽应该拥有相同的等级数据,所以我们使用这样一个享元工厂来创建等级数据,对于相同的怪兽,它们共享同一个等级数据。
使用:
LevelData levelData = LevelDataFactory.GetMonsterLevelData (1);ClientData monster = new ClientData ();monster.Level = 3;monster.AttackPlus = 5;Console.WriteLine (levelData.GetAttack(monster));
这里有一个问题,因为将等级、攻击加成等信息当做外部状态,放在了ClientData里,我们修改这些值得时候,是修改ClientData的实例,但是获取最终结果的时候,却调用的是levelData的方法GetAttack。这样不是很方便,并且容易造成困扰。所以我们可以考虑修改享元模式,把GetAttack的方法写在用户数据里。
为LevelData增加一个抽象方法:
public abstract int GetLevelAttack(int lv);
MonsterLevelData里添加实现:
public override int GetLevelAttack(int lv){lv = System.Math.Min (System.Math.Max (lv, 1), 10);return _levelAttackList[lv - 1];}
创建继承自ClientData的Monster类:
public class Monster : ClientData{LevelData _levelData;public Monster(int monID){_levelData = LevelDataFactory.GetMonsterLevelData (monID);}public int GetAttack(){return _levelData.GetLevelAttack (Level) + AttackPlus;}}
使用:
Monster mon = new Monster (2);mon.Level = 3;mon.AttackPlus = 4;Console.WriteLine (mon.GetAttack ());这样就将内部状态里的方法移动到了外部状态里。调用很方便,也节省了内存。
享元模式的优点在于:减少了运行时对象实例的个数,节省了内存,并且可以集中管理对象的多个状态。
缺点也很明显:个体之间无法相对独立,拥有不同的行为。
1 0
- 小话设计模式(十一)享元模式
- 设计模式学习(十一):享元模式
- JAVA设计模式(十一)----享元模式
- 设计模式之(十一)--享元模式(flyweight)
- Java设计模式之十一(享元模式)
- Java设计模式(十一) 享元模式
- Android设计模式(二十一)-享元模式
- PHP设计模式系列(二十一):享元模式
- (十一)Java设计模式之享元模式
- Java设计模式(十一) 享元模式
- 二十一、享元设计模式
- C++设计模式之十一:Flyweight(享元)
- 设计模式(十一)之 Flyweight(享元)
- 小话设计模式(二十一)策略模式
- 设计模式之(十一)享元模式Flyweight
- 设计模式(十一)----- 享元模式(Flyweight)----(JAVA版)
- java设计模式(十一)——享元模式(Flyweight)
- 大话设计模式-----(十一)享元模式、解释器模式、访问者模式
- 注解
- android开发中AutoCompleteTextView的使用方法
- Spring和Quartz配合实现定时任务
- 数据基本操作——查找
- Spring如何引用properties文件里的配置
- 小话设计模式(十一)享元模式
- AndroidStudio关联源码的解决之道
- 放入多个配置文件时
- 个人记录-LeetCode 7.Reverse Integer
- spring classpath*
- C++ bitset类的使用与简介
- Centos安装(更新)Git
- Memset 初始化问题
- java 用properties文件配置spring数据源,用spring的JdbcTemplate的queryForList查数据