// 유니티로 배우는 게임 디자인 패턴 제 2판 (데이비드 바론, 구진수) 에 대한 공부 노트입니다.
개요
방문자 패턴은 객체 구조에 새로운 기능을 추가할 때, 객체 구조를 변경하기 않도록 기능을 확장할 수 있도록 해주는 디자인 패턴이다. 이 패턴은 기능들을 객체의 클래스들로부터 분리하여 별도의 방문자 객체에 캡슐화함으로써, 객체 구조를 유지하면서 다양한 기능들을 추가할 수 있도록 한다.
구성 요소
- Element : Element는 방문자가 방문할 요소를 의미한다. Element는 주로 Accept라는 매서드를 통해 Visitor의 방문을 허락하고, 이 때 Visitor의 Visit 메서드가 호출된다.
- Visitor : Element를 방문하는 방문자 클래스를 의미한다. Element의 허가가 떨어지면 Element를 방문하여 변수값을 수정하거나, 다양한 기능을 수행할 수 있다. Element에 새로운 기능을 추가하고 싶을 때 Visitor에 새로운 기능들을 작성하고, Element에 방문하여 해당 기능들을 불러와 동작하면 된다.
장단점
장점
- 새로운 기능의 추가가 용이함 : 새로운 기능이 필요할 때마다 요소 클래스를 수정할 필요 없이 새로운 방문자를 추가하거나, 방문자의 기능을 수정하면 된다.
- 개방 / 폐쇄 : 객체지향 프로그래밍의 원칙인 개방/폐쇄 원칙을 따른다.
단점
- 복잡성 증가 : 다른 디자인 패턴들보다 구조적으로 복잡하며, 객체 구조가 간단할 경우 오히려 복잡성을 증가시킬 수 있다.
- 객체 구조에 의존 : 새로운 Element 추가될 때, 모든 Visitor를 수정해야 한다.
구현하기
게임 속의 캐릭터 "킬러" 를 강화하는 기능들을 방문자 패턴을 통해 구현해보자.
Killer는 KillerController, KillerWeapon, KillerMovement 총 세 가지 스크립트로 구성되어 있다. 방문자 패턴을 통해 킬러의 공격력, 이동속도를 강화하는 파워업 기능을 추가해보자.
IVisitor.cs, IElement.cs
먼저, 방문자와 객체의 인터페이스를 작성한다.
// Visitor Interface
public interface IVisitor
{
void Visit(KillerWeapon killerWeapon);
void Visit(KillerMovement killerMovement);
}
// Element Interface
public interface IElement
{
void Accept(IVisitor visitor);
}
Killer관련 스크립트
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KillerController : MonoBehaviour, IElement
{
private List<IElement> _killerElements = new List<IElement>();
public void Accept(IVisitor visitor)
{
foreach (IElement element in _killerElements)
{
element.Accept(visitor);
}
}
void Start()
{
_killerElements.Add(gameObject.AddComponent<KillerWeapon>());
_killerElements.Add(gameObject.AddComponent<KillerMovement>());
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KillerWeapon : MonoBehaviour, IElement
{
public float attackPower = 0;
public float attackSpeed = 0;
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
void OnGUI()
{
GUI.color = Color.red;
GUI.Label(new Rect(125, 40, 200, 20), "Weapon Power : " + attackPower);
GUI.Label(new Rect(125, 60, 200, 20), "Weapon Speed: " + attackSpeed);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KillerMovement : MonoBehaviour, IElement
{
public float movementSpeed = 0;
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
void OnGUI()
{
GUI.color = Color.green;
GUI.Label(new Rect(125, 20, 200, 20), "Movement Speed : " + movementSpeed);
}
}
using System.Collections;
using System.Collections.Generic;
using System.IO.Enumeration;
using UnityEngine;
// 여러가지 파워 업 에셋을 만들기 위해 ScriptableObject를 사용한다.
[CreateAssetMenu(fileName = "PowerUp", menuName = "PowerUp")]
public class KillerPowerUp : ScriptableObject, IVisitor
{
public string powerUpName;
public GameObject powerUpPrefab;
public string powerUpDescriptionl;
[Range(0.0f, 100.0f)]
[Tooltip("AttackPower 0 ~ 100")]
public float attackPower;
[Range(0.0f, 100.0f)]
[Tooltip("AttackSpeed 0% ~ 100%")]
public float attackSpeed;
[Range(0.0f, 1.0f)]
[Tooltip("Movement Speed 0 ~ 1")]
public float movementSpeed;
public void Visit(KillerWeapon killerWeapon)
{
killerWeapon.attackPower += attackPower;
killerWeapon.attackSpeed += attackSpeed;
}
public void Visit(KillerMovement killerMovement)
{
killerMovement.movementSpeed += movementSpeed;
}
}
구현 결과
'Studies > 게임 디자인 패턴' 카테고리의 다른 글
[게임 디자인 패턴] 옵저버 패턴 (0) | 2024.09.24 |
---|---|
[게임 디자인 패턴] 오브젝트 풀 패턴 (7) | 2024.09.10 |
[게임 디자인 패턴] 커맨드 패턴 (0) | 2024.08.05 |
[게임 디자인 패턴] 이벤트 버스 (1) | 2024.07.16 |
[게임 디자인 패턴] 상태 패턴 (1) | 2024.07.10 |
댓글