수색…


RPG 게임에서지도 구현하기

플라이급은 구조적 디자인 패턴 중 하나입니다. 유사한 객체로 가능한 한 많은 데이터를 공유하여 사용 된 메모리 양을 줄이는 데 사용됩니다. 이 문서는 Flyweight DP를 올바르게 사용하는 방법을 알려줍니다.

간단한 예를 들어 당신에게 그 아이디어를 설명해 드리겠습니다. RPG 게임을하고 있으며 캐릭터가 포함 된 거대한 파일을로드해야한다고 가정 해보십시오. 예 :

  • # 잔디입니다. 당신은 그것을 걸을 수 있습니다.
  • $ 가 출발점입니다.
  • @ 는 바위 다. 당신은 그 위에 걸을 수 없습니다.
  • % 는 보물 상자입니다.

지도 샘플 :

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@############@@@@@######@#$@@@

@#############@@@######@###@@@

@#######%######@###########@@@

@############################@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

이러한 객체는 비슷한 특성을 가지므로 각지도 필드에 대해 별도의 객체를 만들 필요가 없습니다. 플라이급 사용 방법을 알려 드리겠습니다.

필드가 구현할 인터페이스를 정의합시다.

public interface IField
{
    string Name { get; }
    char Mark { get; }
    bool CanWalk { get; }
    FieldType Type { get; }
}

이제 필드를 나타내는 클래스를 만들 수 있습니다. 우리는 어떻게 든 그들을 식별해야합니다 (저는 열거 형을 사용했습니다) :

public enum FieldType
{
    GRASS,
    ROCK,
    START,
    CHEST
}
public class Grass : IField
{
    public string Name { get { return "Grass"; } }
    public char Mark { get { return '#'; } }
    public bool CanWalk { get { return true; } }
    public FieldType Type { get { return FieldType.GRASS; } }
}
public class StartingPoint : IField
{
    public string Name { get { return "Starting Point"; } }
    public char Mark { get { return '$'; } }
    public bool CanWalk { get { return true; } }
    public FieldType Type { get { return FieldType.START; } }
}
public class Rock : IField
{
    public string Name { get { return "Rock"; } }
    public char Mark { get { return '@'; } }
    public bool CanWalk { get { return false; } }
    public FieldType Type { get { return FieldType.ROCK; } }
}
public class TreasureChest : IField
{
    public string Name { get { return "Treasure Chest"; } }
    public char Mark { get { return '%'; } }
    public bool CanWalk { get { return true; } } // you can approach it
    public FieldType Type { get { return FieldType.CHEST; } }
}

앞서 말한 것처럼 각 필드에 대해 별도의 인스턴스를 만들 필요가 없습니다. 필드의 저장소 를 만들어야합니다. 플라이급 DP의 본질은 우리가 필요로 할 때만 동적으로 객체를 생성하고 아직 우리의 저장소에 존재하지 않거나 이미 존재한다면 그것을 반환한다는 것입니다. 이것을 처리 할 간단한 클래스를 작성합시다.

public class FieldRepository
{
    private List<IField> lstFields = new List<IField>();

    private IField AddField(FieldType type)
    {
        IField f;
        switch(type)
        {
            case FieldType.GRASS: f = new Grass(); break;
            case FieldType.ROCK: f = new Rock(); break;
            case FieldType.START: f = new StartingPoint(); break;
            case FieldType.CHEST:
            default: f = new TreasureChest(); break;
        }
        lstFields.Add(f); //add it to repository
        Console.WriteLine("Created new instance of {0}", f.Name);
        return f;
    }
    public IField GetField(FieldType type)
    {
        IField f = lstFields.Find(x => x.Type == type);
        if (f != null) return f;
        else return AddField(type);
    }
}

큰! 이제 코드를 테스트 할 수 있습니다.

public class Program
{
    public static void Main(string[] args)
    {
        FieldRepository f = new FieldRepository();
        IField grass = f.GetField(FieldType.GRASS);
        grass = f.GetField(FieldType.ROCK);
        grass = f.GetField(FieldType.GRASS);       
    }
}

콘솔의 결과는 다음과 같아야합니다.

Grass의 새로운 인스턴스 생성

Rock의 새 인스턴스 생성

그러나 우리가 두 번 그것을 원한다면 잔디는 한 번만 나타나는 이유는 무엇입니까? 처음으로 우리가 GetField 잔디 인스턴스를 우리의 저장소에 존재하지 않는다고 부르기 때문에 그것이 생성되었지만, 다음에 우리가 이미 풀을 필요로하므로 우리는 단지 그것을 반환합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow