享元模式
定义
享元模式(Flyweight)
运用共享技术有效地支持大量细粒度的对象。
解释:
大量的对象会出现两个问题:1.内存的大量占用;2.大量对象的创建和销毁时间;
享元模式就是用一种方法去共享“元件”,以减少内存占用和对象数量
UML
成员
在享元模式中,我们将对象成员分为:
1.内在状态 由享元对象自己保存内部状态
2.外在状态 可以动态改变,享元对象需要用到外部状态的方法,在使用时由参数传递对应的外部状态
例如:我们有一个抽象角色类,而士兵类继承自角色类
每个士兵对象都有共同的属性,例如最大生命值、衣着(材质)、速度等,这些属于士兵的内在状态;
每个士兵都有自己的独有的属性,例如位置、血量等,这些属于士兵的外在状态;
享元对象抽象(Flyweight):保存内在状态,并在需要时提供方法以参数的形式使用外部状态;
享元对象实现(FlyweightConcrete):继承自享元对象抽象,并实现相应的方法,保存内在状态
享元对象工厂(FlyweightFactory):以对象池的方式,创建并提供享元对象
代码
享元对象抽象及实现
namespace DesignModel.Flyweight
{
//享元对象抽象
public abstract class Flyweight
{
protected string intrinsic; //内部状态
public Flyweight(string intrinsic)
{
this.intrinsic = intrinsic;
}
public abstract void Operate(string extrinsic); //操作 传入外部状态
}
//享元对象实现
public class FlyweightConcrete : Flyweight
{
public FlyweightConcrete(string intrinsic): base(intrinsic){}
public override void Operate(string extrinsic)
{
Debug.Log("享元对象操作:");
Debug.Log(" 内部状态: " + intrinsic);
Debug.Log(" 外部状态: " + extrinsic);
}
}
}
享元对象工厂
namespace DesignModel.Flyweight
{
public class FlyweightConst
{
public const string A = "A";
public const string B = "B";
public const string C = "C";
}
public class FlyweightFactory
{
private Dictionary<string, Flyweight> flyweightDic;
public FlyweightFactory()
{
flyweightDic = new Dictionary<string, Flyweight>();
flyweightDic.Add(FlyweightConst.A, new FlyweightConcrete(FlyweightConst.A));
flyweightDic.Add(FlyweightConst.B, new FlyweightConcrete(FlyweightConst.B));
flyweightDic.Add(FlyweightConst.C, new FlyweightConcrete(FlyweightConst.C));
}
public Flyweight GetFlyweight(string type)
{
if (!flyweightDic.ContainsKey(type))
{
flyweightDic.Add(type, new FlyweightConcrete(type));
}
return flyweightDic[type];
}
}
}
简单测试
using DesignModel.Flyweight;
public class Client_Flyewight : MonoBehaviour
{
void Start ()
{
FlyweightFactory factory = new FlyweightFactory();
string testX = "testX";
string testY = "testY";
Flyweight f1 = factory.GetFlyweight(FlyweightConst.A);
//一个享元对象使用相同的内部变量 使用不同的外部变量
f1.Operate(testX);
f1.Operate(testY);
Flyweight f2 = factory.GetFlyweight(FlyweightConst.B);
f2.Operate(testX);
Flyweight f3 = factory.GetFlyweight("test");
f3.Operate("zzz");
}
}
测试结果
享元模式应用
优点:
1.将对象的内在成员共享,达到了减少内存占用的目的;
2.使用对象池创建获取内在成员,减少了大量成员的创建和销毁的性能消耗;
缺点:
1.需要将成员区分为内在状态和外在状态,对象系统变得复杂化
应用场景:
1.系统中有大量对象
2.对象数量导致了内存大量内存占用和创建成本
3.这些对象有共同的不变的特征
拓展
在实际应用中,对象池技术就是利用了享元模式的思想,但对象池和享元模式侧重点有所差别
对象池和享元的相同是
1. 都解决了对象的复用
对象池和享元不同的是
1. 对象池中可能会有完全相同的对象,而享元模式中则不会有完全相同的对象
2. 对象池的着力点在于对象的复用,以减少重复创建和销毁
享元模式的着力点在于内在状态的复用,以减少内存占用
二者其实并不冲突
3. 对象池有对象回收,享元模式不需要回收,因为每次派发出去的是同一个对象