zoukankan      html  css  js  c++  java
  • Unity---游戏设计模式(11)之享元模式




    概述参考请看 参考博客

    享元模式:运用共享技术有效地支持大量细粒度的对象。

    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、享元模式优缺点

    优点

    1. 减少了对象的创建,降低了程序内存的占用,提高效率。

    缺点

    1. 提高了系统的复杂度。需要分离出内部状态和外部状态,而外部状态具有固化特性,不应该随着内部状态的改变而改变。
  • 相关阅读:
    Linux Socket函数close() 与 shutdown()区别
    Android Performance Patterns S01E03
    Android Performance Patterns S01E02
    Android Performance Patterns S01E01
    Java类初始化顺序
    原子性,可见性,有序性
    UML类图
    Linux 五种IO模型
    Linux学习笔记(一)
    线程的生命周期-java
  • 原文地址:https://www.cnblogs.com/Fflyqaq/p/11707957.html
Copyright © 2011-2022 走看看