[읽기전에]
UML 다이어그램 : UML클래스 다이어그램 기본상식 http://hongjinhyeon.tistory.com/25
포스팅되는 디자인 패턴의 예는 스타크래프트를 기본으로 하였습니다 : 디자인 패턴을 시작하며 http://hongjinhyeon.tistory.com/24
<기본 정의 >
1. Command Pattern 정의
-커맨드 패턴을 이용하면 요구 사항을 객체로 갭슐화 할 수 있으며, 매개변수를 써서 여러 가지 다른 요구 사항을 집어 넣을수 있다.
또한 요청 내역을 큐에 저장하거나 로그로 기록 할 수 있으며, 작업취소 기능도 지원이 가능하다.
(Encapsulate a request as an object, thereby letting you parameterize clients with different requests,
queue or log requests, and support undoable operations.)
2. UML Diagram
3. 사용용도 및 장점
-사용자의 요청을 객체화 시킴으로써 ( 객체 안에 작업에 필요한 모든 내용이 들어가있음 ), 그 객체만 있으면 해당 커맨드가 어떤
작업을 수행했는지 알 수가있다. 그럼으로 해서 다시 취소작업을 수행한다거나 로그기능을 구현이 가능하다.
-커맨트 패턴은 커맨드에 알맞은 파라미터만 전달해주면 알아서 결과가 처리가된다. (예) 계산기
요청만 하면 내부적으로 알고리즘에 의해서 자동으로 처리가 된다.
4. 소스
using System; namespace DoFactory.GangOfFour.Command.Structural { /// <summary> /// MainApp startup class for Structural /// Command Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into console application. /// </summary> static void Main() { // Create receiver, command, and invoker Receiver receiver = new Receiver(); Command command = new ConcreteCommand(receiver); Invoker invoker = new Invoker(); // Set and execute command invoker.SetCommand(command); invoker.ExecuteCommand(); // Wait for user Console.ReadKey(); } } /// <summary> /// The 'Command' abstract class /// </summary> abstract class Command { protected Receiver receiver; // Constructor public Command(Receiver receiver) { this.receiver = receiver; } public abstract void Execute(); } /// <summary> /// The 'ConcreteCommand' class /// </summary> class ConcreteCommand : Command { // Constructor public ConcreteCommand(Receiver receiver) : base(receiver) { } public override void Execute() { receiver.Action(); } } /// <summary> /// The 'Receiver' class /// </summary> class Receiver { public void Action() { Console.WriteLine("Called Receiver.Action()"); } } /// <summary> /// The 'Invoker' class /// </summary> class Invoker { private Command _command; public void SetCommand(Command command) { this._command = command; } public void ExecuteCommand() { _command.Execute(); } } }
-main 부분이 Client에 해당합니다.
5. 실행결과
Called Receiver.Action()
< 실제 적용 >
1. UML Diagram
2. 사용용도 및 장점
-스타크래프트에서 커맨드 패턴을 찾기가 힘들었습니다. Redo, Undo가 되는게 없더군요. 그와중에 발견한 스타크래프트 맵을 만들어주는 에디터(빙고)
-맵 에디터에서 유닛들을 배치하거나 지형(언덕, 물, 미네랄등)을 배치하고 다시 Undo도 할수잇고 Redo도 가능합니다.
-하나 하나의 명령어들을 객체화함으로써 Undo나 Redo가 가능하게 됩니다.
3. 소스
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Command { class Program { static void Main(string[] args) { MapEditor mapEditor = new MapEditor(); mapEditor.Create("마린1", "100", "200"); mapEditor.Create("마린2", "200", "400"); mapEditor.Create("마린3", "300", "600"); mapEditor.Delete("마린2", "300", "600"); mapEditor.Undo(3); mapEditor.Redo(3); Console.ReadKey(); } /// <summary> /// Receiver 클래스 /// </summary> class UnitManger { public void CreatUnit(string _unitName, string _pointX, string _pointY) { Console.WriteLine("[{0}] 유닛을 X좌표 {1} , Y좌표 {2} 위치에 생성합니다.", _unitName, _pointX, _pointY); } public void DeleteUnit(string _unitName, string _pointX, string _pointY) { Console.WriteLine("[{0}] 유닛을 X좌표 {1} , Y좌표 {2} 위치에서 삭제합니다.", _unitName, _pointX, _pointY); } } /// <summary> /// 추상 Command 생성 /// </summary> abstract class Command { public string unitName; public string pointX; public string pointY; public abstract void Execute(); } /// <summary> /// 유닛 생성 Concreate 객체 생성 /// </summary> class CreatCommand : Command { private UnitManger unitManger; /// <summary> /// 생성자 /// </summary> /// <param name="_unitManger"></param> public CreatCommand(UnitManger _unitManger, string _unitName, string _pointX, string _pointY) { this.unitManger = _unitManger; this.unitName = _unitName; this.pointX = _pointX; this.pointY = _pointY; } public override void Execute() { unitManger.CreatUnit(this.unitName, this.pointX, this.pointY); } } /// <summary> /// 유닛 삭제 Concreate 객체 생성 /// </summary> class DeleteCommand : Command { private UnitManger unitManger; /// <summary> /// 생성자 /// </summary> /// <param name="_unitManger"></param> public DeleteCommand(UnitManger _unitManger, string _unitName, string _pointX, string _pointY) { this.unitManger = _unitManger; this.unitName = _unitName; this.pointX = _pointX; this.pointY = _pointY; } public override void Execute() { unitManger.DeleteUnit(this.unitName, this.pointX, this.pointY); } } class MapEditor { private UnitManger _uintManger = new UnitManger(); private List<Command> _commands = new List<Command>(); private int _current = 0; public void Create(string _unitName, string _pointX, string _pointY) { Command command = new CreatCommand(_uintManger, _unitName, _pointX, _pointY); command.Execute(); _commands.Add(command); _current++; } public void Delete(string _unitName, string _pointX, string _pointY) { Command command = new DeleteCommand(_uintManger, _unitName, _pointX, _pointY); command.Execute(); _commands.Add(command); _current++; } public void Redo(int levels) { Console.WriteLine("\n---- Redo {0} levels ", levels); for (int i = 0; i < levels; i++) { if (_current <= _commands.Count - 1) { Command command = _commands[_current++]; command.Execute(); } } } public void Undo(int levels) { Console.WriteLine("\n---- Undo {0} levels ", levels); // Perform undo operations for (int i = 0; i < levels; i++) { if (_current > 0) { Command command = _commands[--_current] as Command; if ((command as CreatCommand) != null) { //생성일때 삭제처리 Command commandTemp = new DeleteCommand(_uintManger, command.unitName, command.pointX, command.pointY); commandTemp.Execute(); } else { //삭제일때 생성처리 Command commandTemp = new CreatCommand(_uintManger, command.unitName, command.pointX, command.pointY); commandTemp.Execute(); } } } } } } }
4. 실행결과
5. 피드백
-커맨드 패턴의 핵심은 사용자의 요구사항 자체를 객체로 캡슐화 하는것이다.
-처음 UML 다이어그램을 봤을때 이게 먼가할정도로 좀 꼬여서 서로를 생성하고 소유하는거 같습니다.
-커맨드를 주문서, 인보커를 종업원, 리시버를 주방정 정도로 생각하시면 됩니다.
[참조]
-http://www.dofactory.com
-Head First Design Patterns
'프로젝트 설계 > 디자인 패턴' 카테고리의 다른 글
11. Iterator Pattern ( 이터레이터 / 반복자 패턴 C# ) (3) | 2012.10.09 |
---|---|
10. State Pattern ( 스테이트 / 상태 패턴 C# ) (4) | 2012.09.11 |
8. Strategy Pattern ( 스트래티지 / 전략 패턴 C# ) (9) | 2012.09.06 |
7. Observer Pattern ( 옵져버 패턴 C# ) (3) | 2012.09.05 |
6. Facade Pattern (퍼사드 패턴 C# ) (2) | 2012.09.04 |