요청을 객체의 형태로 캡슐화하여 사용자가 보낸 요청을 나중에 이용할 수 있도록 메서드 이름, 매개 변수 등 요청에 필요한 정보를 저장 또는 로깅, 취소할 수 있게 하는 패턴이다.
디자인 패턴은 개념만 보면 이해하기 쉽지만, 실제로 사용할려면 잘 안되는 경우가 많습니다.
그래서 사용하는 이유와 예시, 예제 코드를 보면 좀 더 실용적인 개념이 될 것이라 생각했습니다.
가장 큰 이유는 관심사 분리의 원칙(SoC, Separation of Concerns)을 지킬 수 있게 합니다.
아래의 사진은 레스토랑에서 손님이 주문을 하는 상황입니다.
상황 1)
첫 번째 레스토랑은 주방에 있는 직원이 요리도 하고 직접 주문을 받습니다.
상황 2)
두 번째 상황은 키오스크 주문을 통해 주문서를 한번에 관리하고 있습니다.
개선된 점
abstract class Command
{
protected Kiosk _kiosk;
public void setKiosk (Kiosk kiosk)
{
this._kiosk = kiosk;
}
public abstract void execute();
}
class OrderPushCommand : Command
{
private Menu menu;
public OrderPushCommand(Menu menu)
{
this.menu = menu;
}
public override void execute()
{
_kiosk.OrderPush(menu);
}
}
class OrderPopCommand : Command
{
public override void execute()
{
_kiosk.OrderPop();
}
}
// 키오스크를 활용해 주문 Queue에 push 및 pop을 합니다.
class Kiosk
{
Queue<Menu> _orderQueue = new Queue<Menu>();
Cooker cooker;
public Kiosk(Cooker cooker)
{
this.cooker = cooker;
}
public void OrderPush(Menu menu)
{
_orderQueue.Enqueue(menu);
}
// 주문 Queue에서 menu를 pop 합니다.
public void OrderPop()
{
if (_orderQueue.Count == 0)
{
Console.WriteLine("요리할 메뉴가 없습니다.");
return;
}
Menu menu = _orderQueue.Dequeue();
cooker.Cooking(menu);
}
}
// 주방장(요리사)이 요리를 합니다.
class Cooker
{
// 주방장(요리사)이 메뉴에 맞게 요리를 합니다.
public void Cooking(Menu menu)
{
Console.WriteLine("------------------------------------");
Console.WriteLine("요리사가 요리를 시작합니다.");
foreach (string menuName in menu._menuList)
Console.WriteLine(menuName);
Console.WriteLine("요리가 완료되었습니다.");
Console.WriteLine("------------------------------------");
}
}
// 메뉴를 List에 저장합니다.
class Menu
{
public List<string> _menuList = new List<string>();
public void addMenu(string menuName)
{
_menuList.Add(menuName);
}
}
class baekTest
{
static void Main(string[] args)
{
// 키오스크(Kiosk)와 Cooker(주방장) 객체를 생성합니다.
Cooker cooker = new Cooker();
Kiosk kiosk = new Kiosk(cooker);
// 메뉴를 선택합니다.
Menu menu = new Menu();
menu.addMenu("파스타");
menu.addMenu("콜라");
// 커맨드 객체를 생성합니다.
// OrderPushCommand 생성 시 menu를 전달합니다.
Command orderPushCommand = new OrderPushCommand(menu);
Command orderPopCommand = new OrderPopCommand();
// 커맨드를 실행 할 키오스를 set 합니다.
orderPushCommand.setKiosk(kiosk);
orderPopCommand.setKiosk(kiosk);
// 커맨드를 실행합니다.
orderPushCommand.execute();
orderPopCommand.execute();
}
}
예제 코드를 실행 시 위와 같은 결과가 나오게 됩니다.
구현하면서 키오스크 객체에서 메서드를 직접 실행하는 방식보다 좀 더 간결하고,
커맨드를 List 형식으로 저장해서 한번에 실행도 가능할 것 같다고 생각했습니다.
디자인 패턴을 단순히 예제 코드를 따라 치는게 아니라,
다른 상황과 연결 시켜서 직접 구현보았습니다.