이전 글 "같은 종류 다른 타입 리팩토링"에서 이어진다.
Enum을 이용해서 Key 아이템을 다른 타입인지를 판단해서 구분한다.
또한 추상 클래스를 이용해서 중복되는 코드 부분을 단축시킨다.
이번 리팩토링을 통해서 Enum의 사용법과 추상클리스의 실사용을 경험하였다.
public class LockObject : MonoBehaviour
{
[SerializeField] private GameObject KeyDoor;
[SerializeField] private AudioSource OpenDoorSound;
private BoxCollider _doorCollider;
private Animator _doorAnimator;
enum Color {Blue, Green, Red };
[SerializeField] private Color _keycolor;
private void Start()
{
_doorCollider = KeyDoor.GetComponentInChildren<BoxCollider>();
_doorAnimator = KeyDoor.GetComponentInChildren<Animator>();
}
public string GetInteractPrompt()
{ // C
if (Main.Player.KeyCheck.Blue == true && _keycolor == Color.Blue)
return string.Format("Open {0} Door", _keycolor);
else if (Main.Player.KeyCheck.Red == true && _keycolor == Color.Red)
return string.Format("Open {0} Door", _keycolor);
else if (Main.Player.KeyCheck.Green == true && _keycolor == Color.Green)
return string.Format("Open {0} Door", _keycolor);
else
return string.Format("Need {0} Key", _keycolor);
}
public void OnInteract()
{
if (Main.Player.KeyCheck.Blue == true && _keycolor == Color.Blue)
DoorInteraction();
if (Main.Player.KeyCheck.Red == true && _keycolor == Color.Red)
DoorInteraction();
if (Main.Player.KeyCheck.Green == true && _keycolor == Color.Green)
DoorInteraction();
}
public void DoorInteraction()
{
_doorAnimator.SetTrigger("OpenDoor");
Main.Game.CallDoorOpen();
Destroy(_doorCollider);
if (!OpenDoorSound.isPlaying)
OpenDoorSound.Play();
}
}
1. Key의 타입이 무엇인지 판별하는 곳에서 코드가 중복된다.
2. Key를 가지고 있는지 판별하는 bool 값이 변수가 3개며, 중복된다
public abstract class Door : MonoBehaviour, IInteractable
{
[SerializeField] private GameObject KeyDoor;
[SerializeField] private AudioSource OpenDoorSound;
private BoxCollider _doorCollider;
private Animator _doorAnimator;
private void Start()
{
_doorCollider = KeyDoor.GetComponentInChildren<BoxCollider>();
_doorAnimator = KeyDoor.GetComponentInChildren<Animator>();
}
public abstract string GetInteractPrompt();
public virtual void OnInteract()
{
DoorInteraction();
}
public void DoorInteraction()
{
_doorAnimator.SetTrigger("OpenDoor");
Main.Game.CallDoorOpen();
Destroy(_doorCollider);
if (!OpenDoorSound.isPlaying)
OpenDoorSound.Play();
}
}
추상 클래스로 Door를 만들어서 기본적으로 중복되는 변수 선언과 할당을 하나로 만들었다.
IIteractable
로 만든 GetInteractPrompt() 와 OnInteract()를 추상클라스와 virtual로 만들었다.
중복되는 내부함수 DoorInteraction()을 사용하기 위해 OnInteract()는 virtual로 만들었고,
GetInteractPrompt는 Door 클래스를 상속받은 자식 클래스에서 모두 따로 작성하기 위해 추상메서드로 만들었다.
# 기존 함수
public class KeyCheck
{
public ItemType KeyColor = ItemType.None;
public bool Red { get; set; }
public bool Blue { get; set; }
public bool Green { get; set; }
}
기존에 3가지로 키 색깔 변수를 지정했던 것을 아래로 바꾸었다.
public enum ItemType
{
None,
RedKey,
BlueKey,
GreenKey
}
public class KeyCheck
{
public ItemType KeyColor = ItemType.None;
}
Enum을 사용하면서 알게 된 사실은 아래와 같다
enum은 클래스와 같은 역할을 하기에 Class 내부가 아니라 바깥에 선언해주어야 한다.
# 빨간 문
public class RedDoor : Door
{
ItemType _keyColor = ItemType.RedKey;
public override string GetInteractPrompt()
{
if(Main.Player.KeyCheck.KeyColor != _keyColor)
{
return "Need" + _keyColor;
}
return "Open" + _keyColor + "Door";
}
public override void OnInteract()
{
if (Main.Player.KeyCheck.KeyColor != _keyColor)
return;
base.OnInteract();
}
}
# 파란 문
public class BlueDoor : Door
{
ItemType _keyColor = ItemType.BlueKey;
public override string GetInteractPrompt()
{
if (Main.Player.KeyCheck.KeyColor != _keyColor)
{
return "Need" + _keyColor;
}
return "Open" + _keyColor + "Door";
}
public override void OnInteract()
{
if (Main.Player.KeyCheck.KeyColor != _keyColor)
return;
base.OnInteract();
}
}
#초록 문
public class GreenDoor : Door
{
ItemType _keyColor = ItemType.GreenKey;
public override string GetInteractPrompt()
{
if (Main.Player.KeyCheck.KeyColor != _keyColor)
{
return "Need" + _keyColor;
}
return "Open" + _keyColor + "Door";
}
public override void OnInteract()
{
if (Main.Player.KeyCheck.KeyColor != _keyColor)
return;
base.OnInteract();
}
}
자식 클래스 내부에 ItemType을 선언해서 각 객체의 색을 정해주었다.
이렇게 작성하고보니 매개변수로 색깔만 정해주어도 좋았을 거라는 생각은 든다.
이렇게 전략 패턴을 이용해서 아이템 객체에 따라서 다르게 실행되는 코드를 작성할 수 있었다.