[Java] Java에서 콜백 패턴 구현하기
카테고리: Java
Callback 이란?
callback 은 하위 객체가 상위 객체에게 자신의 상태를 알려줄 때 사용하는 개념입니다. C# 에서는 이 콜백을 하게 해주는 delegate
라는 녀석이 있습니다. 한국어로 직역하면 대리자
정도로 해석이 됩니다.
이 대리자가 하위 객체에서 상위객체로 자신의 상태를 알려주는 주체가 됩니다. 만약, 필요한 정보가 있다면, 그 정보까지 실어서 보내주게 됩니다.
하지만 Java 에서는 해당 delegate 라는 키워드가 존재하지 않아서, 인터페이스를 활용하여 패턴을 구현해야 합니다.
강의를 할 때 콜백에 대한 내용이 나오면 학생들이 많이 어려워 하는 것 같습니다.
저도 처음에는 엄청 어려웠는데, Callback을 완전히 깨닫게 된게 언제였지를 떠올려보면, Java로 콜백을 구현할 때 였던 것 같습니다.
Java 에서의 콜백 구현
VoidVoidDelegate 구현
Java에서는 콜백을 구현할 때, 인터페이스를 활용하게 됩니다.
우선 인터페이스를 하나 만듭니다.
🗅 interface VoidVoidDelegateImpl
public interface VoidVoidDelegateImpl {
public void VoidVoidDelegate();
}
그 다음 해당 인터페이스를 인자로 받는 함수를 만듭니다. 그리고 해당 객체가 Null 이 아닐 때, 어떤 구현이 들어있는지는 모르지만, 인터페이스의 함수 VoidVoidDelegate 를 실행시킵니다.
(C#에서는 callback?.Invoke() 랑 같습니다.) (이 함수가 static 인 이유는 main 함수가 static 이기 때문에, static 한 main 함수에 올릴려면, 올릴 함수도 static 해야 하기 때문입니다.)
public class Main
{
//여기가 실행부
//C의 VoidMain, C#의 Main 클래스랑 같은 역할임
public static void main(String[] args)
{
}
//인터페이스를 인자로 받아서 그 안에 있는 함수를 실행시킬 것임
//인터페이스는 내부 구현이 안되어있기 때문에 이 함수에서는 그냥 뭐가 들어올지 모르지만 일단 함수를 실행시킴
//나중에 호출하는 부분에서 그 함수를 정의하여서 로직을 수행하게 함
public static void VoidVoidCallback(SomeCallbackInterface _callback)
{
if(_callback!=null)
{
_callback.SomeCallback();
}
}
}
이제 이 함수를 호출 합니다.
🗅 class Main
public class Main
{
//여기가 실행부
//C의 VoidMain, C#의 Main 클래스랑 같은 역할임
public static void main(String[] args)
{
//여기서 함수 실행
//자바에서는 함수의 인자로 인터페이스를 넣을 수 있음
VoidVoidCallback(new SomeCallbackInterface()
{
@Override
public void SomeCallback()
{
System.out.println("VoidVoidDelegate!");
}
});
}
//인터페이스를 인자로 받아서 그 안에 있는 함수를 실행시킬 것임
//인터페이스는 내부 구현이 안되어있기 때문에 이 함수에서는 그냥 뭐가 들어올지 모르지만 일단 함수를 실행시킴
//나중에 호출하는 부분에서 그 함수를 정의하여서 로직을 수행하게 함
public static void VoidVoidCallback(VoidVoidDelegateImpl _callback)
{
if(_callback!=null)
{
_callback.SomeCallback();
}
}
}
이렇게 새로운 인터페이스를 만든 다음에, 구현되어 있지 않고, 정의만 되어 있던 VoidVoidDelegate
함수를 정의해주기만 하면 됩니다.
그러면 _callback.VoidVoidDelegate()
를 실행할 때, 재정의된 행동이 발동 할겁니다.
VoidIntDelegate 구현
자 이제, 반환형이 Void 이고, 인자로 Int 값을 받는 콜백을 구현해 보겠습니다.
🗅 interface VoidIntDelegateImpl
public interface VoidIntDelegateImpl{
public void VoidIntDelegate(int _int);
}
마찬가지로 함수를 만들어 줍니다.
public class Main
{
//여기가 실행부
//C의 VoidMain, C#의 Main 클래스랑 같은 역할임
public static void main(String[] args)
{
//여기서 함수 실행
//자바에서는 함수의 인자로 인터페이스를 넣을 수 있음
VoidVoidCallback(new SomeCallbackInterface()
{
@Override
public void SomeCallback()
{
System.out.println("VoidVoidDelegate!");
}
});
}
//인터페이스를 인자로 받아서 그 안에 있는 함수를 실행시킬 것임
//인터페이스는 내부 구현이 안되어있기 때문에 이 함수에서는 그냥 뭐가 들어올지 모르지만 일단 함수를 실행시킴
//나중에 호출하는 부분에서 그 함수를 정의하여서 로직을 수행하게 함
public static void VoidVoidCallback(VoidVoidDelegateImpl _callback)
{
if(_callback!=null)
{
_callback.SomeCallback();
}
}
public static void VoidIntCallback(VoidIntDelegateImpl _callback)
{
if(_callback!=null)
{
_callback.VoidVoidDelegate(10);
}
}
}
이 함수에서 매개변수로 10을 던져줍니다. 이렇게 하면 재정의 하는 부분에서, 10이라는 숫자를 인자로 받아서 사용할 수 있습니다.
(C# 에서는 callback?.Invoke(10) 이랑 같은 표현 입니다.)
이제 똑같이, 메인 함수에서 해당 함수를 불러 보겠습니다.
🗅 class Main
public class Main
{
//여기가 실행부
//C의 VoidMain, C#의 Main 클래스랑 같은 역할임
public static void main(String[] args)
{
//여기서 함수 실행
//자바에서는 함수의 인자로 인터페이스를 넣을 수 있음
VoidVoidCallback(new VoidVoidDelegateImpl()
{
@Override
public void VoidVoidDelegate()
{
System.out.println("VoidVoidDelegate!");
}
});
/////////////////////////////////////////////////////////
VoidIntCallback(new VoidIntDelegate()
{
@Override
public void VoidIntDelegate(int _int)
{ //_int에 10 이라는 정보가 담겨져서 들어올 것임
System.out.println("VoidIntDelegate!" + _int);
}
});
}
//인터페이스를 인자로 받아서 그 안에 있는 함수를 실행시킬 것임
//인터페이스는 내부 구현이 안되어있기 때문에 이 함수에서는 그냥 뭐가 들어올지 모르지만 일단 함수를 실행시킴
//나중에 호출하는 부분에서 그 함수를 정의하여서 로직을 수행하게 함
public static void VoidVoidCallback(VoidVoidDelegateImpl _callback)
{
if(_callback!=null)
{
_callback.VoidVoidDelegate();
}
}
public static void VoidIntCallback(VoidIntDelegateImpl _callback)
{
if(_callback!=null)
{
_callback.VoidIntDelegate(10);
}
}
}
이렇게 해주면, Callback!10
이라는 문구가 출력이 됩니다.
댓글 남기기