Unity - 대리자, 람다식

김도현·2023년 11월 24일
0

TIL

목록 보기
66/76

이 글을 작성하는 이유

필자가 상점 및 거래관련된 기능을 구현하면서 돈을 외부에서 수정할 수 없도록 구현하면서 MVC패턴을 최대한 구현하고자 생각하고 노력했던 결과를 잊지않고자 적을려고 합니다.

대리자란?

대리자는 그 말 그대로 대리로 무엇을 해주는 것을 의미하는데 필드나 지역변수처럼 메서드도 선언하여 호출할 수 있는것을 말합니다.

대리자의 종류

1. 델리게이트

C#의 Delegate는 간단히 말하면 C++의 함수포인터를 생각하면 된다

접근자 delegate 반환타입 이름(매개변수)

private void Start()
{
	delegate test = new 이름(사용할 매서드);
    test(매개변수);
}
Async

delegate의 비동기 작업은 일반적으로 멀티스레딩을 구현할 때 사용된다. 델리게이트를 통해서 메서드의 실행을 다른 스레드에게 위임하여 해당 스레드에서 비동기적으로 작업을 처리하고, 작업이 완료되면 해당 스레드가 호출한 스레드에게 결과를 알려준다. 이 작업 방식은 보통 결과를 필요로 하지 않는 작업을 빠르고 효율적으로 처리하기 위해서 사용한다.

보통 BeginInvoke()와 EndInvoke() 메서드를 활용해서 비동기를 구현한다.

  • BeginInvoke : 해당 작업을 다른 스레드에서 비동기적으로 실행

  • EndInvoke : 해당 작업이 완료되었는지 확인 후 결과를 반환

public delegate int AsyncMethodDelegate(int x, int y);

public class Calculator
{
    public int Add(int x, int y)
    {
        return x + y;
    }

	// Add 메서드를 비동기적으로 실행
    public void AddAsync(int x, int y, AsyncCallback callback)
    {
        AsyncMethodDelegate asyncMethod = new AsyncMethodDelegate(Add);
        // 작업이 종료되면 callback
        asyncMethod.BeginInvoke(x, y, callback, null);
    }
}

public class Program
{
    static void Main(string[] args)
    {
        Calculator calculator = new Calculator();
        AsyncCallback callback = new AsyncCallback(CalculateCompleted);

        calculator.AddAsync(1, 2, callback);
		
        Console.ReadLine();
    }
	
    // callback 호출 함수
    static void CalculateCompleted(IAsyncResult ar)
    {
        AsyncResult result = (AsyncResult)ar;
        AsyncMethodDelegate asyncMethod = (AsyncMethodDelegate)result.AsyncDelegate;

        int resultValue = asyncMethod.EndInvoke(ar);
        Console.WriteLine("Result: " + resultValue);
    }
}

2. Event

프로그래밍에서 이벤트는 어떤 특정한 조건이나 상황이 발생했을 때 이를 감지하고 처리하는 기능을 의미한다.

예를 들어 마우스 클릭, 키보드 입력 등이 이벤트이다. 이벤트 기반 프로그래밍(Event-driven programming)은 이러한 상황에서 반응하듯이 특정한 기능을 수행시키는 이벤트 기반으로 만드는 방식을 말하며 코드와의 상호작용으로 객체 간의 통신을 쉽게하고 객체의 라이프 사이클과 관련된 처리를 간편하게 할 수 있다.

3. Action

마찬가지로 delegate를 매번 선언하기 귀찮을 수 있다. 이에 따라서 C#에서는 미리 delegate 변수를 정의해놨다.
반환 타입이 없을 경우 : Action

4. Func

반환 타입이 있을 경우 : Func

MVC패턴이란?

Model, View, Controller의 약자이며 Model에서는 데이터를 보관, Contoroller에서 처리 및 전달, View에서 데이터 표시하는 패턴입니다.

결과

private Func<int, int, int> sellItem;
private Func<int, int, int> byitem;
private Func<int, int, int> repurchase;

public Func<int, int, bool> trySellItem;
public Func<int, int, bool> tryByitem;
public Func<int, int, bool> tryRepurchase;

public void Init(Func<int, int, int> newSellItem, Func<int, int, int> newByItem, Func<int, int, int> newRepurchase)
{
    sellItem = newSellItem;
    byitem = newByItem;
    repurchase = newRepurchase;
}

 private void Start()
 {
     trySellItem = (itemID, itemCount) => SellItem(sellItem(itemID, itemCount));
     tryByitem = (itemID, itemCount) => Byitem(byitem(itemID, itemCount));
     tryRepurchase = (itemID, itemCount) => Repurchase(repurchase(itemID, itemCount));
 }
 
 private bool SellItem(int addMoney)
{
    if (addMoney != 0)
    {
        playerMoney += addMoney;
        CallOnMoneyTextUpdate();
        return true;
    }
    return false;  
}

private bool Byitem(int addMoney)
{
    if (addMoney != 0)
    {
        playerMoney -= addMoney;
        CallOnMoneyTextUpdate();
        return true;
    }
    return false; 
}

private bool Repurchase(int addMoney)
{
    if (addMoney != 0)
    {
        playerMoney -= addMoney;
        CallOnMoneyTextUpdate();
        return true;
    }
    return false;
}
 

이렇게 구현한 이유
플레이어의 돈을 함부로 수정할 수 없게 막고 싶었으며 확장성이 높았으면 좋겠다고 싶었다. 하지만 MVC패턴으로 구현할려면 Data를 저장하는 곳에서 처리를 진행하면 안되기에 외부에서 현재갖고있는 돈과 아이템 가격을 비교하여 true시 0초과의 금액을 반환해 주면서 아이템을 추가 및 제거를 실행, false시 0을 반환의 기능을 구현하여 호출하여 금액 계산를 해주고 싶었다

여기서 호출되는 메서드도 private로 선언되어 접근을 막고싶었기에 메서드로 호출하는게 아닌 Func으로 호출하는 것이다.

0개의 댓글