4-2 Making Abstract Methods Concrete
本章繼上一章同樣要重構我們的技能系統,大家應該會發現在每一個技能的config裡面,無論是PowerAttackConfig、SelfHealConfig,還是AreaEffectConfig都有如下圖的AddComponent方法,並且都有同樣重複的一行:behaviourComponent.SetConfig(this)
所以這次重構也是將這重複的一行移動到父類別,而唯獨不重複的部分,亦即需要指定Behaviour的部分,則由子類別來實作。我們打開AbilityConfig.cs,並將AddComponent方法改成AttachAbilityTo,如下圖,其中呼叫了新的抽象方法GetBehaviourComponent則由子類別來實作。
接著,如下圖SelfHealConfig.cs要實作GetBehaviourComponent,則回傳SelfHealBehaviour,看起來簡單清爽多了。
以下提供修正過的所有程式碼:
AbilityConfig.cs:
SelfHealConfig.cs:
AreaEffectConfig.cs:
PowerAttackConfig.cs:
所以這次重構也是將這重複的一行移動到父類別,而唯獨不重複的部分,亦即需要指定Behaviour的部分,則由子類別來實作。我們打開AbilityConfig.cs,並將AddComponent方法改成AttachAbilityTo,如下圖,其中呼叫了新的抽象方法GetBehaviourComponent則由子類別來實作。
接著,如下圖SelfHealConfig.cs要實作GetBehaviourComponent,則回傳SelfHealBehaviour,看起來簡單清爽多了。
以下提供修正過的所有程式碼:
AbilityConfig.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; using RPG.Core; namespace RPG.Character{ public struct AbilityParams{ public Enemy target; public float baseDamage; public AbilityParams(Enemy target, float baseDamage){ this.target = target; this.baseDamage = baseDamage; } } public abstract class AbilityConfig : ScriptableObject { [Header("Special Ability General")] [SerializeField] float energyCost = 10f; [SerializeField] GameObject particlePrefab = null; [SerializeField] AudioClip audioClip = null; public AbilityBehaviour AttachAbilityTo (GameObject gameObjectAttachTo){ AbilityBehaviour behaviourComponent = GetBehaviourComponent(gameObjectAttachTo); behaviourComponent.SetConfig (this); return behaviourComponent; } public abstract AbilityBehaviour GetBehaviourComponent(GameObject gameObjectAttachTo); public float GetEnergyCost(){ return energyCost; } public GameObject GetParticlePrefab(){ return particlePrefab; } public AudioClip GetAudioClip(){ return audioClip; } } }
SelfHealConfig.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace RPG.Character{ [CreateAssetMenu(menuName= ("RPG/Special Ability/Self Heal"))] public class SelfHealConfig : AbilityConfig { [Header("Self Heal Specific")] [SerializeField] float extraHealth = 5f; public override AbilityBehaviour GetBehaviourComponent (GameObject gameObjectAttachTo){ return gameObjectAttachTo.AddComponent(); } public float GetExtraHealth(){ return extraHealth; } } }
AreaEffectConfig.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace RPG.Character{ [CreateAssetMenu(menuName= ("RPG/Special Ability/Area Effect"))] public class AreaEffectConfig : AbilityConfig { [Header("Area Effect Specific")] [SerializeField] float radius = 5f; [SerializeField] float damageToEachTarget = 15f; public override AbilityBehaviour GetBehaviourComponent (GameObject gameObjectAttachTo){ return gameObjectAttachTo.AddComponent(); } public float GetDamageToEachTarget(){ return damageToEachTarget; } public float GetRadius(){ return radius; } } }
PowerAttackConfig.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; namespace RPG.Character{ [CreateAssetMenu(menuName= ("RPG/Special Ability/Power Attack"))] public class PowerAttackConfig : AbilityConfig { [Header("Power Attack Specific")] [SerializeField] float extraDamage = 10f; public override AbilityBehaviour GetBehaviourComponent (GameObject gameObjectAttachTo){ return gameObjectAttachTo.AddComponent(); } public float GetExtraDamage(){ return extraDamage; } } }
留言
張貼留言