概述参考请看 参考博客
享元模式:运用共享技术有效地支持大量细粒度的对象。
1、享元模式原型
享元模式原型UML图
享元模式原型代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Client : MonoBehaviour
{
private void Start () {
FlyWeightFactory FlyWeightFactory = new FlyWeightFactory();
FlyWeight FlyWeight1 = FlyWeightFactory.GetFlyWeight("MyFlyWeight");
FlyWeight1.Operate();
FlyWeight FlyWeight2 = FlyWeightFactory.GetFlyWeight("MyFlyWeight");
FlyWeight2.Operate();
FlyWeight FlyWeight3 = FlyWeightFactory.GetFlyWeight("YourFlyWeight");
FlyWeight3.Operate();
FlyWeight FlyWeight4 = FlyWeightFactory.GetFlyWeight("YourFlyWeight");
FlyWeight4.Operate();
FlyWeightFactory.ShowAllFlyWeights();
}
}
/// <summary>
/// 享元抽象类
/// </summary>
public abstract class FlyWeight
{
//享元模式的内部状态可以共享,但不会随环境的变化而变化。
//外部状态不可以共享,但会随环境的变化而变化。这里说的是外部状态具有固化特性,即固有化的性质,不应该随【内部状态】的改变而改变,否则会导致系统的逻辑混乱
//内部状态
public string mInside;
//外部状态
protected string mOutside;
public string Outside { get { return mOutside; } set { mOutside = Outside; } }
public FlyWeight(string outside)
{
mOutside = outside;
}
public abstract void Operate();
}
/// <summary>
/// 具体的享元类
/// </summary>
public class ConcreteFlyWeight : FlyWeight
{
public ConcreteFlyWeight(string outside)
:base(outside)
{}
public override void Operate()
{
Debug.Log("外部状态:" + mOutside);
}
}
/// <summary>
/// 享元工厂
/// </summary>
public class FlyWeightFactory
{
private Dictionary<string, FlyWeight> mFlyWeightDict;
public FlyWeightFactory()
{
mFlyWeightDict = new Dictionary<string, FlyWeight>();
}
/// <summary>
/// 获取FlyWeight
/// </summary>
public FlyWeight GetFlyWeight(string name)
{
if (mFlyWeightDict.ContainsKey(name))
{
Debug.Log(name + ":已经存在字典中,直接返回");
return mFlyWeightDict[name];
}
FlyWeight FlyWeight = new ConcreteFlyWeight(name);
mFlyWeightDict.Add(name, FlyWeight);
Debug.Log(name + ":不存在字典中,加入字典再返回");
return FlyWeight;
}
public void ShowAllFlyWeights()
{
foreach (FlyWeight item in mFlyWeightDict.Values)
{
Debug.Log("FlyWeight:" + item.Outside);
}
}
}
2、享元模式实例
假设有青铜、白银、黄金三种敌人。
创建每种敌人时,每种敌人的基本属性是相同的。比如名字、血量之类的。
这些相同的基本属性如果我们每次创建角色时都重新构造,无疑麻烦而且占性能。
当我们使用(10)建造者模式来建造复杂的角色时,就可以在添加基本属性一步时,并使用享元模式直接获取到角色基本属性。
这里不再重复给出建造模式代码了,只给出了享元模式的部分代码
实例代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Client : MonoBehaviour
{
private void Start()
{
//假设有青铜、白银、黄金三种敌人。
//创建每种敌人时,每种敌人的基本属性是相同的。比如名字、血量之类的。
//这些相同的基本属性如果我们每次创建角色时都重新构造,无疑麻烦而且占性能。
//当我们使用(10)的建造者模式来建造复杂的角色时,就可以在建造基本属性一步时,使用享元模式直接获取到角色属性。
//这里不再重复给出建造模式代码了,只给出了享元模式的部分代码
EnemyFactory factory = new EnemyFactory();
EnemyBaseAttribute bronzeBaseAttribute = factory.GetEnemyBaseAttribute(EnemyType.Bronze);
Debug.Log(bronzeBaseAttribute.Name + "血量:" + bronzeBaseAttribute.HP);
EnemyBaseAttribute silverBaseAttribute = factory.GetEnemyBaseAttribute(EnemyType.Silver);
Debug.Log(silverBaseAttribute.Name + "血量:" + silverBaseAttribute.HP);
EnemyBaseAttribute goldBaseAttribute = factory.GetEnemyBaseAttribute(EnemyType.Gold);
Debug.Log(goldBaseAttribute.Name + "血量:" + goldBaseAttribute.HP);
}
}
public enum EnemyType
{
Bronze, //青铜
Silver, //白银
Gold //黄金
}
/// <summary>
/// 敌人相同的基本属性
/// </summary>
public class EnemyBaseAttribute
{
#region 基本属性
private string mName;
private int mHP;
private float mMoveSpeed;
private string mPrefabName;
#endregion
#region Get方法
public string Name { get { return mName; } }
public int HP { get { return mHP; } }
public float MoveSpeed { get { return mMoveSpeed; } }
public string PrefabName { get { return mPrefabName; } }
#endregion
public EnemyBaseAttribute(string name,int hp,float moveSpeed,string prefabName)
{
mName = name;
mHP = hp;
mMoveSpeed = moveSpeed;
mPrefabName = prefabName;
}
}
/// <summary>
/// 角色基本属性的工厂(更像享元模式和工厂模式一起用)
/// </summary>
public class EnemyFactory
{
//存储每个敌人类型对应的基本属性
private Dictionary<EnemyType, EnemyBaseAttribute> mEnemyBaseAttributeDict;
public EnemyFactory()
{
mEnemyBaseAttributeDict = new Dictionary<EnemyType, EnemyBaseAttribute>();
InitEnemyBaseAttributeDict();
}
/// <summary>
/// 初始化三种敌人基本属性
/// </summary>
private void InitEnemyBaseAttributeDict()
{
mEnemyBaseAttributeDict.Add(EnemyType.Bronze, new EnemyBaseAttribute("青铜", 10, 1, "BronzeModel"));
mEnemyBaseAttributeDict.Add(EnemyType.Silver, new EnemyBaseAttribute("白银", 30, 3, "SilverModel"));
mEnemyBaseAttributeDict.Add(EnemyType.Gold, new EnemyBaseAttribute("黄金", 20, 2, "GoldModel"));
}
/// <summary>
/// 获取敌人基本属性
/// </summary>
public EnemyBaseAttribute GetEnemyBaseAttribute(EnemyType type)
{
if (mEnemyBaseAttributeDict.ContainsKey(type))
{
return mEnemyBaseAttributeDict[type];
}
Debug.LogError("无法根据类型" + type + "得到角色基础属性");
return null;
}
}
3、享元模式优缺点
优点
- 减少了对象的创建,降低了程序内存的占用,提高效率。
缺点
- 提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化特性,不应该随着内部状态的改变而改变。