이번 챕터에서는 컴포지트 패턴을 이터레이터 패턴에 이어서 같은 주제, monster info와 weapon info로 소개하겠습니다.
컴포지트 패턴의 정의
객체들을 트리구조로 구성하여 부분 - 전체 계층구조를 구현합니다.
컴포지트 패턴을 이용하면 개별객체와 복합객체를 똑같은 방법으로 다룰 수 있게 됩니다.
이전시간에 배운 이터레이터 패턴과 혼합하여 설명하자면 복합객체인 iterator와 개별객체인 item이 구분할 필요가 없어,
item을 가진 iterator를 가진 그위에 iterator를 가지는 형태, 즉 트리구조로 복합객체를 만들어갈 수 있습니다.
복합객체와 개별객체가 상속받을 infoComponent를 만들었습니다.
복합객체와 개별객체의 구분을 없애줄 것입니다.
public abstract class InfoComponent
{
public virtual InfoComponent GetChild(int _index)
{
return null;
}
public virtual string GetName()
{
return string.Empty;
}
public virtual string GetDescription()
{
return string.Empty;
}
public virtual void Print()
{
//
}
}
이터레이터 내부에 들어가며 info component를 상속받는 monster info와 weapon info입니다
public class MonsterInfo : InfoComponent
{
public string name = string.Empty;
public int hp = 0;
public MonsterInfo(string _name, int _hp)
{
this.name = _name;
this.hp = _hp;
}
public override string GetName()
{
string monsterName = $"이름 : {this.name}";
return monsterName;
}
public override string GetDescription()
{
string description = $"체력 : {this.hp}";
return description;
}
public override void Print()
{
Debug.Log($"{this.GetName()}/{this.GetDescription()}");
}
}
public class WeaponInfo : InfoComponent
{
public string name = string.Empty;
public int damage = 0;
public WeaponInfo(string _name, int _damage)
{
this.name = _name;
this.damage = _damage;
}
public override string GetName()
{
string monsterName = $"이름 : {this.name}";
return monsterName;
}
public override string GetDescription()
{
string description = $"공격력 : {this.damage}";
return description;
}
public override void Print()
{
Debug.Log($"{this.GetName()}/{this.GetDescription()}");
}
}
그리고 이터레이터로 사용했던 monsteriterator, weaponIterator또한 info component를 상속받아
함수들을 구현해줍니다. 위에 info들과 다른점은 iterator 내부 info들의 print를 호출해주도록 Print를 구현해줍니다.
public class MonsterIterator : InfoComponent, Iterator
{
private List<InfoComponent> infos = new List<InfoComponent>();
private int index = -1;
public string name = string.Empty;
public string description = string.Empty;
public MonsterIterator(string _name, string _description)
{
this.name = _name;
this.description = _description;
this.index = 0;
}
public void Add(InfoComponent _infoComponent)
{
this.infos.Add(_infoComponent);
}
public bool HasNext()
{
bool _hasNext = this.index < this.infos.Count;
return _hasNext;
}
public InfoComponent Next()
{
return this.infos[this.index++];
}
public void Remove(InfoComponent _target)
{
this.infos.Remove(_target);
}
public override void Print()
{
Debug.Log($"--------------------------------------------");
Debug.Log($"{this.GetName()}/{this.GetDescription()}");
Debug.Log($"--------------------------------------------");
while (this.HasNext())
{
this.Next().Print();
}
}
public override string GetName()
{
return this.name;
}
public override string GetDescription()
{
return this.description;
}
}
public class WeaponIterator : InfoComponent, Iterator
{
private InfoComponent[] infos = {};
private int index = -1;
public string name = string.Empty;
public string description = string.Empty;
public WeaponIterator(string _name, string _description)
{
this.name = _name;
this.description = _description;
this.index = -1;
}
public void Add(InfoComponent _infoComponent)
{
InfoComponent[] beforeArray = this.infos;
this.infos = new InfoComponent[this.infos.Length + 1];
int count = 0;
while (count >= beforeArray.Length)
{
this.infos[count] = beforeArray[count];
count++;
}
this.infos[count] = _infoComponent;
}
public bool HasNext()
{
bool _hasNext = this.index < this.infos.Length;
return _hasNext;
}
public InfoComponent Next()
{
return this.infos[this.index++];
}
public void Remove(InfoComponent _target)
{
// this.infos.Remove(_target);
}
public override void Print()
{
Debug.Log($"--------------------------------------------");
Debug.Log($"{this.GetName()}/{this.GetDescription()}");
Debug.Log($"--------------------------------------------");
while (this.HasNext())
{
this.Next().Print();
}
}
public override string GetName()
{
return this.name;
}
public override string GetDescription()
{
return this.description;
}
}
마지막으로 실행부입니다.
public class IteratorCheck : MonoBehaviour
{
private List<Iterator> iterators = new List<Iterator>();
private MonsterInfo[] monsterInfos = {new MonsterInfo("고블린", 1), new MonsterInfo("스켈레톤", 2), new MonsterInfo("오크", 3), new MonsterInfo("드래곤", 4)};
private WeaponInfo[] weaponInfos = {new WeaponInfo("검", 1), new WeaponInfo("도끼", 2), new WeaponInfo("화살", 3), new WeaponInfo("창", 4)};
void Start()
{
this.SetIterator("몬스터 리스트", "몬스터 정보를 출력해줍시다.", this.monsterInfos);
this.SetIterator("무기 리스트", "무기 정보를 출력해줍시다.", this.weaponInfos);
this.PrintInfos();
}
private void SetIterator(string _name, string _description, InfoComponent[] _infos)
{
Iterator iterator = new MonsterIterator(_name, _description);
for (int i = 0; i < _infos.Length; i++)
{
iterator.Add(_infos[i]);
}
this.iterators.Add(iterator);
}
void PrintInfos()
{
for (int i = 0; i < this.iterators.Count; i++)
{
InfoComponent infoComponent = (InfoComponent)this.iterators[i];
infoComponent.Print();
}
}
}
로그로 나온 결과로써 Print함수 하나로 다수의 iterator와 그 내부에 있는 info들의 속성들을 순차적으로 호출되는것을 확인할 수 있었습니다.
안정성부분에서 살짝 위험하다고 하지만 뭔가 신기한 느낌의 패턴이었다.
존재한다는 것만 알아두면 될 것 같다... 게임 구현에 있어서 좋은 파트가 생각나질 않는다.
'게임 개발 > 디자인 패턴' 카테고리의 다른 글
[디자인 패턴] 11. 유니티에서 이터레이터 패턴 (0) | 2021.11.09 |
---|---|
[디자인패턴] 10. 유니티에서 템플릿 메소드 패턴 (2) | 2021.10.26 |
[디자인패턴] 9. 유니티에서의 어댑터 패턴 퍼사드 패턴 (2) | 2021.09.30 |
[디자인패턴] 8. 유니티에서의 커맨드 패턴 (0) | 2021.09.23 |
[디자인패턴] 7. 유니티에서 데코레이터 패턴 (0) | 2021.08.22 |