设计模式实战学习笔记(四):享元、组合、命令模式

(十一)享元模式:

当相同的角色(如多个新手士兵)共享多个不变的属性时,使不变的属性只存在一份(会变化的属性如 当前生命值、等级…),每次要使用的时候,就去储存相同属性的BaseAttr工厂中取得该属性,可减少所占用的内存。

——重构代码——

完成战士/敌人角色的构造(使用享元) :

将ICharacterAttr 中的基础属性删除,创建CharacterBaseAttr用于管理角色的相同基础属性:

/// <summary>
///管理游戏角色共有的属性
/// </summary>
public class CharacterBaseAttr
{
    protected string mName;
    protected int mMaxHp;
    protected float mMoveSpeed;
    protected string mIconSprite; // 资源加载
    protected string mPrefabName;// 通过Prefab名字实例化Prefab
    protected float mCritRate;//0-1暴击率

    public CharacterBaseAttr(string Name, int MaxHp, float MoveSpeed, string IconSprite, string PrefabName, float CritRate)
    {
        this.mName = Name;
        this.mMaxHp = MaxHp;
        this.mMoveSpeed = MoveSpeed;
        this.mIconSprite = IconSprite;
        this.mPrefabName = PrefabName;
        this.mCritRate = CritRate;
    }

    public string Name { get { return mName; } }
    public int MaxHp { get { return mMaxHp; } }
    public float MoveSpeed { get { return mMoveSpeed; } }
    public string IconSprite { get { return mIconSprite; } }
    public string PrefabName { get { return mPrefabName; } }
    public float CritRate { get { return mCritRate; } }
}

创建工厂接口类IAttrFactory,写入用于得到角色基础的方法:

public interface IAttrFactory
{
    CharacterBaseAttr GetCharacterBaseAttr(System.Type t);
}

创建工厂类AttrFactory(享元模式核心),用字典将 通过战士/敌人的类型来存储战士/敌人的基础属性,每次实例化战士/敌人只需要调用 得到角色基础属性的方法 ,不需要每次都在内存中存一份相同的基础属性。构造方法中将所有需要共享的对象初始化

/// <summary>
/// 享元模式核心 
/// </summary>
public class AttrFactory : IAttrFactory
{
    //通过角色类型来存储角色共有的属性
    private Dictionary<Type, CharacterBaseAttr> mCharacterBaseAttrDict;

    /// <summary>
    /// 构造方法中将所有需要共享的对象初始化
    /// </summary>
    public AttrFactory()
    {
        InitCharacterBaseAttr();
    }

    private void InitCharacterBaseAttr()
    {
        //初始化字典
        mCharacterBaseAttrDict = new Dictionary<Type, CharacterBaseAttr>();

        mCharacterBaseAttrDict.Add(typeof(SoldierRookie), new CharacterBaseAttr("新手士兵", 80, 2.5f, "RookieIcon", "Soldier3", 0));
        mCharacterBaseAttrDict.Add(typeof(SoldierSergeant), new CharacterBaseAttr("中士士兵", 90, 3, "SergeantIcon", "Soldier2", 0));
        mCharacterBaseAttrDict.Add(typeof(SoldierCaptain), new CharacterBaseAttr("上尉士兵", 100, 3, "CaptainIcon", "Soldier1", 0));

        mCharacterBaseAttrDict.Add(typeof(EnemyElf), new CharacterBaseAttr("小精灵", 100, 3, "ElfIcon", "Enemy1", 0.2f));
        mCharacterBaseAttrDict.Add(typeof(EnemyOgre), new CharacterBaseAttr("怪物", 120, 2, "OgreIcon", "Enemy2", 0.3f));
        mCharacterBaseAttrDict.Add(typeof(EnemyTroll), new CharacterBaseAttr("巨魔", 200, 1, "TrollIcon", "Enemy3", 0.2f));
    }
    /// <summary>
    /// 得到角色基础属性
    /// </summary>
    /// <param name="t"></param>
    /// <returns></returns>
    public CharacterBaseAttr GetCharacterBaseAttr(Type t)
    {
        if (mCharacterBaseAttrDict.ContainsKey(t) == false)
        {
            Debug.LogWarning("无法根据类型["+t+"]得到角色的基础属性"); return null;
        }
        return mCharacterBaseAttrDict[t];
    }

}

在FactoryManager中加入IAttrFactory 静态属性,可用于外界调用:

public static class FactoryManager
{
    private static IAssetFactory mAssetFactory;
    private static IWeaponFactory mWeaponFactory;
    private static ICharacterFactory mSoldierFactory;
    private static ICharacterFactory mEnemyFactory;
    private static IAttrFactory mAttrFactory;

    public static IAttrFactory attrFactory
    {
        get
        {
            if (mAttrFactory== null)
            {
                mAttrFactory= new ResourcesAssetFactory();
            }
            return mAttrFactory;
        }
    }
省略………

在ICharacterAttr中声明可被子类取得的属性 CharacterBaseAttr , 修改其构造方法,将基础属性 改为 CharacterBaseAttr类,并修改其子类的构造方法:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ICharacterAttr
{
    protected CharacterBaseAttr mCharacterBaseAttr;

    protected int mLv;
    protected int mCurrentHP;
    protected int mDmgDescValue; //减少的伤害

    public int CurrentHP { get { return mCurrentHP; } }

    private IAttrStrategy mStrategy;

    //角色实例化时就决定属性,后续不改变
    public ICharacterAttr(IAttrStrategy strategy, int lv, CharacterBaseAttr characterBaseAttr)
    {
        mCharacterBaseAttr = characterBaseAttr;
        mLv = lv;

        mStrategy = strategy;
        mDmgDescValue = mStrategy.GetCritDmg(mCharacterBaseAttr.CritRate);
        mCurrentHP = mCharacterBaseAttr.MaxHp + mStrategy.GetExtraHPValue(mLv);
    }
    public int CritValue { get { return mStrategy.GetCritDmg(mCharacterBaseAttr.CritRate); } }

    /// <summary>
    /// 被攻击后的处理
    /// </summary>
    /// <param name="damage">受到的伤害</param>
    public void TakeDamege(int damage)
    {
        damage -= mDmgDescValue;
        if (damage <= 5) damage = 5;
        mCurrentHP -= damage;
    }
}

修改SoldierBuilder 和 EnemyrBuilder的 AddCharacterAttr()  给角色添加属性的方法:

 

通过FactoryManager调用attrFactory 属性工厂的 GetCharacterBaseAttr()方法,得到角色基础属性:

public class SoldierBuilder : ICharacterBuilder
{
 
    public SoldierBuilder(ICharacter character, Type t, WeaponType weaponType, Vector3 spawnPos, int lv) : base(character, t, weaponType, spawnPos, lv){
    }

    public override void AddCharacterAttr()
    {
        CharacterBaseAttr characterBaseAttr =  FactoryManager.attrFactory.GetCharacterBaseAttr(mT);
        mPrefabName = characterBaseAttr.PrefabName;
        ICharacterAttr attr = new SoldierAttr(new SoldierAttrStrategy(), mLV, characterBaseAttr);
        mCharacter.CharacterAttri = attr;
    }
public class EnemyrBuilder : ICharacterBuilder
{
    public EnemyrBuilder(ICharacter character, Type t, WeaponType weaponType, Vector3 spawnPos, int lv) : base(character, t, weaponType, spawnPos, lv){ }

    public override void AddCharacterAttr()
    {
        CharacterBaseAttr characterBaseAttr = FactoryManager.attrFactory.GetCharacterBaseAttr(mT);
        mPrefabName = characterBaseAttr.PrefabName;
        ICharacterAttr attr = new EnemyAttr(new EnemyAttrStrategy(), mLV, characterBaseAttr);
        mCharacter.CharacterAttri = attr;
    }
省略……

将武器属性修改为享元模式 :

将IWeaponAttr 中的基础属性删除,创建CharacterBaseAttr用于管理角色的基础属性:

public class WeaponBaseAttr
{
    protected string mName;
    protected int mAtk;//最大攻击力
    protected float mAtkRange;//最大攻击范围
    protected string mAssetsName;//资源名称

    public WeaponBaseAttr(string Name,int Atk,float AtkRange,string AssetsName)
    {
        mName = Name;
        mAtk = Atk;
        mAtkRange = AtkRange;
        mAssetsName = AssetsName;
    }

    public string Name { get { return mName; } }
    public int Atk { get { return Atk; } }
    public float AtkRange { get { return mAtkRange; } }
    public string AssetsName { get { return mAssetsName; } }
}

在IWeaponAttr  中声明可被子类取得的属性 WeaponBaseAttr , 修改其构造方法,将基础属性 改为 WeaponBaseAttr 类,并

修改其子类的构造方法

public abstract class IWeapon
{

    //protected int mAtkPlusValue;//暴击
    protected WeaponBaseAttr mWeaponBaseAttr;

    protected GameObject mGameObject;//武器模型
    protected ICharacter mOwner;//武器持有者
    protected ParticleSystem mParticle;//武器特效
    protected LineRenderer mLineRender;//武器射线
    protected Light mLight;
    protected AudioSource mAudioSource; //音效

    protected float mEffectDisplayTime;//特效显示时间

    public float AtkRange { get { return mWeaponBaseAttr.AtkRange; } }
    public float Atk { get { return mWeaponBaseAttr.Atk; } } // 武器攻击力
    public ICharacter Owner { set { mOwner = value; } }
    public GameObject gameObject { get { return mGameObject; } }

    public IWeapon(WeaponBaseAttr weaponBaseAttr, GameObject gameObject)
    {
        mWeaponBaseAttr = weaponBaseAttr;
        mGameObject = gameObject;
        //得到武器特效射线灯光音效的组件,在武器的子物体Effect中
        Transform effect = mGameObject.transform.Find("Effect");
        mParticle = effect.GetComponent<ParticleSystem>();
        mLineRender = effect.GetComponent<LineRenderer>();
        mLight = effect.GetComponent<Light>();
        mAudioSource = effect.GetComponent<AudioSource>();
    }

在IAttrFactory中加入得到武器基础属性的方法:

public interface IAttrFactory
{
    CharacterBaseAttr GetCharacterBaseAttr(System.Type t);
    WeaponBaseAttr GetWeaponBaseAttr(WeaponType weaponType);
}

在AttrFactory中用字典将 通过武器的类型来存储武器的基础属性,每次实例化武器只需要调用 得到角色基础属性的方法 ,不需要每次都在内存中存一份相同的基础属性构造方法中将所有需要共享的对象初始化

/// <summary>
/// 享元模式核心 
/// </summary>
public class AttrFactory : IAttrFactory
{
    //通过角色类型来存储角色共有的属性
    private Dictionary<Type, CharacterBaseAttr> mCharacterBaseAttrDict;
    private Dictionary<WeaponType, WeaponBaseAttr> mWeaponBaseAttrDict;

    /// <summary>
    /// 构造方法中将所有需要共享的对象初始化
    /// </summary>
    public AttrFactory()
    {
        InitCharacterBaseAttr();
        InitWeaponBaseAttr();
    }

    private void InitWeaponBaseAttr()
    {
        //初始化字典
        mWeaponBaseAttrDict = new Dictionary<WeaponType, WeaponBaseAttr>();

        mWeaponBaseAttrDict.Add(WeaponType.Gun, new WeaponBaseAttr("手枪",20, 5, "WeaponGun"));
        mWeaponBaseAttrDict.Add(WeaponType.Rifle, new WeaponBaseAttr("长枪",30, 7, "WeaponRifle"));
        mWeaponBaseAttrDict.Add(WeaponType.Rocket, new WeaponBaseAttr("火箭",40, 8, "WeaponRocket"));
    }

    private void InitCharacterBaseAttr()
    {
        //初始化字典
        mCharacterBaseAttrDict = new Dictionary<Type, CharacterBaseAttr>();

        mCharacterBaseAttrDict.Add(typeof(SoldierRookie), new CharacterBaseAttr("新手士兵", 80, 2.5f, "RookieIcon", "Soldier3", 0));
        mCharacterBaseAttrDict.Add(typeof(SoldierSergeant), new CharacterBaseAttr("中士士兵", 90, 3, "SergeantIcon", "Soldier2", 0));
        mCharacterBaseAttrDict.Add(typeof(SoldierCaptain), new CharacterBaseAttr("上尉士兵", 100, 3, "CaptainIcon", "Soldier1", 0));

        mCharacterBaseAttrDict.Add(typeof(EnemyElf), new CharacterBaseAttr("小精灵", 100, 3, "ElfIcon", "Enemy1", 0.2f));
        mCharacterBaseAttrDict.Add(typeof(EnemyOgre), new CharacterBaseAttr("小精灵", 120, 2, "OgreIcon", "Enemy2", 0.3f));
        mCharacterBaseAttrDict.Add(typeof(EnemyElf), new CharacterBaseAttr("巨魔", 200, 1, "TrollIcon", "Enemy3", 0.2f));
    }
    /// <summary>
    /// 得到角色基础属性
    /// </summary>
    /// <param name="t"></param>
    /// <returns></returns>
    public CharacterBaseAttr GetCharacterBaseAttr(Type t)
    {
        if (mCharacterBaseAttrDict.ContainsKey(t) == false)
        {
            Debug.LogWarning("无法根据类型["+t+"]得到角色的基础属性"); return null;
        }
        return mCharacterBaseAttrDict[t];
    }

    /// <summary>
    /// 得到武器基础属性
    /// </summary>
    /// <param name="weaponType"></param>
    /// <returns></returns>
    public WeaponBaseAttr GetWeaponBaseAttr(WeaponType weaponType)
    {
        if(mWeaponBaseAttrDict.ContainsKey(weaponType) == false
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值