1. 享元模式

所谓“享元”,顾名思义就是被共享的单元。享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象。具体来讲,当一个系统中存在大量重复对象的时候,我们就可以利用享元模式,将对象设计成享元,在内存中只保留一份实例,供多处代码引用,这样可以减少内存中对象的数量,以起到节省内存的目的。实际上,不仅仅相同对象可以设计成享元,对于相似对象,我们也可以将这些对象中相同的部分(字段),提取出来设计成享元,让这些大量相似对象引用这些享元。

2. 享元模式的实现

享元模式的代码实现非常简单,主要是通过工厂模式,在工厂类中,通过一个 Map 或者 List 来缓存已经创建好的享元对象,以达到复用的目的

3. 享元模式 VS 单例 ,缓存,对象池

应用单例模式是为了保证对象全局唯一。应用享元模式是为了实现对象复用,节省内存。缓存是为了提高访问效率,而非复用。池化技术中的“复用”理解为“重复使用”,主要是为了节省时间。

4. 代码实现

1. 代码示例结构✅

类名

角色

说明

TreeType

享元对象(Flyweight)

包含可共享的树类型数据(贴图、颜色)

Tree

使用享元的对象

包含位置、大小等外部状态,引用共享的 TreeType

TreeFactory

享元工厂

缓存并复用 TreeType 实例

Forest

管理所有树

创建和渲染树对象

Program

控制台入口

模拟执行

2. 代码

    public class CompositeDesign
    {
        // static void Main()
        // {

        //     Entity entity = new Entity("哥布林");


        //     entity.AddComponent(new MoveComponent());
        //     entity.AddComponent(new AttackComponent());
        //     entity.AddComponent(new DropComponent());

        //     entity.Update();
        // }
    }
    /// <summary>
    /// 组件接口
    /// </summary>
    public interface IComponent
    {
        public void Update(Entity entity);
    }
    // 抽象实体
    public class Entity
    {
        public string Name { get; }

        private List<IComponent> compsites = new List<IComponent>();

        public Entity(string name)
        {
            this.Name = name;
        }

        public void AddComponent(IComponent component)
        {
            compsites.Add(component);
        }

        public void Update()
        {
            foreach (var component in compsites)
            {
                component.Update(this);
            }
        }
    }

    // 具体实体
    public class MoveComponent : IComponent
    {
        public void Update(Entity entity)
        {
            Console.WriteLine($"{entity.Name} 正在移动...");
        }
    }

    public class AttackComponent : IComponent
    {
        public void Update(Entity entity)
        {
            Console.WriteLine($"{entity.Name} 发起攻击!");
        }
    }

    public class DropComponent : IComponent
    {
        public void Update(Entity entity)
        {
            Console.WriteLine($"{entity.Name} 死后掉落战利品。");
        }
    }