享元模式 - Unity

享元模式

享元模式是对象结构型模式,此模式为了处理大量的细粒度对象所导致的内存不足的解决方案。它通过运用共享技术来支持大量细粒度对象的复用,它通过共享已经存在的对象来大幅减少需要创建的对象数量(主要是内部状态的数量),从而避免大量的相似类的开销。

其中线程池,字符串池等,是最为常见的运用。在游戏开发中,我们需要对游戏中大量的对象的创建进行复用,其中包括粒子,模型等,大多数都是通过享元模式。这个模式对于游戏开发十分重要。

结构

在这里插入图片描述

说明

  • 抽象享元(Flyweight)- 定义子享元类的公有方法,且方法本身依赖于外部状态,通过参数进行数据交互。
  • 具体享元(Concrete Flyweight)- 实现具体方法,并将内部状态初始化。
  • 享元工厂(Flyweight Factory)- 负责创建和管理享元对象,本身可作为单例。
  • 外部状态(External State)- 享元对象需要的数据,但其本身会变化,将它以外部参数的形式传入,从而完成方法。

享元模式中,为了追求对象共享,我们将对象的信息分为两个部分

  • 内部状态 :指对象共享出来的部分,本身不会改变。
  • 外部状态:指对象中会随环境改变的变量,他们不存在享元对象中,而是通过参数传入。

实现

这里我们举一个游戏粒子的例子。

抽象粒子 - 抽象享元(定义内部状态)

    public abstract class ParticleFlyweight
    {
        protected readonly string _name;
        protected readonly float _size;
        protected readonly float _lifeTime;

        protected ParticleFlyweight(string name, float size, float lifeTime)
        {
            _name = name;
            _size = size;
            _lifeTime = lifeTime;
        }

        public abstract void Release(ExternalStateParticle externalState);
    }

粒子1,2 - 具体享元

    public class Particle1 : ParticleFlyweight
    {
        public Particle1() : base(
            "Particle1", 
            10f, 
            3f)
        {
        }

        public override void Release(ExternalStateParticle externalState)
        {
            Debug.Log(_name + "粒子,大小为" + _size + ",在" + externalState.Position + 
                      "位置,旋转为" + externalState.Quaternion + ",速度为" +externalState.Speed + 
                      ",生命周期为" + _lifeTime + ",释放");
        }
    }


    public class Particle2 : ParticleFlyweight
    {
        public Particle2() : base(
            "Particle2", 
            5f, 
            5f)
        {
        }

        public override void Release(ExternalStateParticle externalState)
        {
            Debug.Log(_name + "粒子,大小为" + _size + ",在" + externalState.Position + 
                      "位置,旋转为" + externalState.Quaternion + ",速度为" +externalState.Speed + 
                      ",生命周期为" + _lifeTime + ",释放");
        }
    }

外部粒子 - 外部状态

    public struct ExternalStateParticle
    {
        public Vector3 Position;
        public Quaternion Quaternion;
        public float Speed;

        public ExternalStateParticle(Vector3 position, Quaternion quaternion, float speed)
        {
            this.Position = position;
            this.Quaternion = quaternion;
            this.Speed = speed;
        }
    }

粒子工厂 - 享元工厂

    public class ParticleFactory
    {
        private Dictionary<string, ParticleFlyweight> _particle;
        private static ParticleFactory _instance = new ParticleFactory();

        public static ParticleFactory Instance => _instance;

        private ParticleFactory()
        {
            _particle = new Dictionary<string, ParticleFlyweight>();
            _particle.Add("1", new Particle1());
            _particle.Add("2", new Particle2());
        }

        public ParticleFlyweight GetParticleFlyweight(string key) =>
            key switch
            {
                "1" => _particle["1"],
                "2" => _particle["2"],
                _ => throw new ArgumentException("key 这个参数不存在"),
            };
    }

粒子 - (内部状态 + 外部状态 = 完整粒子)

    public class Particle
    {
        private ParticleFlyweight _internalState;
        private ExternalStateParticle _externalState;
        public Particle(ParticleFlyweight internalState, ExternalStateParticle externalState)
        {
            _internalState = internalState;
            _externalState = externalState;
        }

        public void Release() => _internalState.Release(_externalState);
    }

调用

    public class FlyweightExample : MonoBehaviour
    {
        private void Start()
        {
            ParticleFlyweight internalState1 = ParticleFactory.Instance.GetParticleFlyweight("1");
            ParticleFlyweight internalState2 = ParticleFactory.Instance.GetParticleFlyweight("2");

            ExternalStateParticle externalState1 = new ExternalStateParticle(
                new Vector3(0f, 0f, 0f),
                new Quaternion(0f, 0f, 0f, 1),
                1.0f);
            ExternalStateParticle externalState2 = new ExternalStateParticle(
                new Vector3(0f, 0f, 0f),
                new Quaternion(0f, 0f, 0f, 1),
                2.0f);

            Particle particle1 = new Particle(internalState1, externalState1);
            Particle particle2 = new Particle(internalState2, externalState2);
            
            particle1.Release();
            particle2.Release();
        }
    }

在这里插入图片描述

应用场景

  • 当程序中存在大量的相似的对象时,即大量细粒度对象,为节约内存容量,应该使用享元模式。

利与弊

优点

  • 节约资源,避免创建大量的相同的对象数据。

缺点

  • 由于享元模式将原本完整的对象数据分成两部分,导致执行方法过程,每次都需传入数据,增加执行时间。
  • 容易使系统复杂。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值