필자가 상점 및 거래관련된 기능을 구현하면서 돈을 외부에서 수정할 수 없도록 구현하면서 MVC패턴을 최대한 구현하고자 생각하고 노력했던 결과를 잊지않고자 적을려고 합니다.
대리자는 그 말 그대로 대리로 무엇을 해주는 것을 의미하는데 필드나 지역변수처럼 메서드도 선언하여 호출할 수 있는것을 말합니다.
C#의 Delegate는 간단히 말하면 C++의 함수포인터를 생각하면 된다
접근자 delegate 반환타입 이름(매개변수)
private void Start()
{
delegate test = new 이름(사용할 매서드);
test(매개변수);
}
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);
}
}
프로그래밍에서 이벤트는 어떤 특정한 조건이나 상황이 발생했을 때 이를 감지하고 처리하는 기능을 의미한다.
예를 들어 마우스 클릭, 키보드 입력 등이 이벤트이다. 이벤트 기반 프로그래밍(Event-driven programming)은 이러한 상황에서 반응하듯이 특정한 기능을 수행시키는 이벤트 기반으로 만드는 방식을 말하며 코드와의 상호작용으로 객체 간의 통신을 쉽게하고 객체의 라이프 사이클과 관련된 처리를 간편하게 할 수 있다.
마찬가지로 delegate를 매번 선언하기 귀찮을 수 있다. 이에 따라서 C#에서는 미리 delegate 변수를 정의해놨다.
반환 타입이 없을 경우 : Action
반환 타입이 있을 경우 : Func
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으로 호출하는 것이다.