介面隔離原則(Interface segregation principle
):不應該讓一個類(class)為了實作某個介面(interface)而去讓這個類實作用不到的方法,簡單的說就是要避免一個大型的介面(interface)
。最簡單的思考方向是使用單一職責(singleresponsibility principle)去考慮,讓每個介面保持單一並簡單。
假設要製作一個策略遊戲,這個遊戲有多個角色單位,每個單位會有血量,速度,等狀態,
可能會想將這些單位的狀態抽象為一個介面,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public interface IUnitStats { float Health { get; set; } int Defense { get; set; } void Die(); void TakeDamage(); void RestoreHealth(); float MoveSpeed { get; set; } float Acceleration { get; set; } void GoForward(); void Reverse(); void TurnLeft(); void TurnRight(); int Strength { get; set; } int Dexterity { get; set; } int Endurance { get; set; } }
|
但是在遊戲中,有會有一些不可移動但是可以破壞的物件,這些物件也會需要生命值(Health),但是不需要移動相關的方法(如GoForward),因此這個介面太臃腫了。
可以考慮將這些行為切割為較小的介面,每個介面負責專一的職責
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public interface IMovable { float MoveSpeed { get; set; } float Acceleration { get; set; } void GoForward(); void Reverse(); void TurnLeft(); void TurnRight(); } public interface IDamageable { float Health { get; set; } int Defense { get; set; } void Die(); void TakeDamage(); void RestoreHealth(); } public interface IUnitStats { int Strength { get; set; } int Dexterity { get; set; } int Endurance { get; set; } }
|
在實作時,敵人單位會移動,有狀態,並且是可損壞的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class EnemyUnit : MonoBehaviour, IDamageable, IMovable, IUnitStats { public float Health { get; set; } public int Defense { get; set; } public float MoveSpeed { get; set; } public float Acceleration { get; set; } public int Strength { get; set; } public int Dexterity { get; set; } public int Endurance { get; set; }
public void Die() { ... } public void TakeDamage() { ... } public void RestoreHealth() { ... } public void GoForward() { ... } public void Reverse() { ... } public void TurnLeft() { ... } public void TurnRight() { ... } }
|
箱子只能被損壞
1 2 3 4 5 6 7 8 9
| public class Box : MonoBehaviour, IDamageable { public float Health { get; set; } public int Defense { get; set; }
public void Die() { ... } public void TakeDamage() { ... } public void RestoreHealth() { ... } }
|
這樣,每個類只需要實作其所需的介面,避免了因為實作不必要的方法而增加的複雜性。