Command Pattern 커맨드 패턴을 액션스크립트로 컨버팅 – Head First Design Pattern
by 세계의끝 on 6.18, 2009, under Design Pattern
헤드퍼스트 디자인 패턴의 제 6 장 커맨드 패턴 입니다. 커맨드 패턴은 객체지향 프로그래밍에서 가장 중요한 패턴 중 하나이므로 최소한의 커맨드 패턴을 적용하여 개념에 대한 이해를 돕는 포스트로부터 시작하여 차근차근 단계를 밟아 몇개의 포스트로 나눠서 작성 하겠습니다. 이 포스트는 그 중 가장 간단한 형태의 커맨드 패턴에 대해 다룹니다.
먼저 커맨드 패턴에 대한 정의를 보겠습니다.
커맨드 패턴 – 커맨드 패턴을 이용하면 요구 사항을 객체로 캡슐화 할 수 있으며, 매개변수를 써서 여러 가지 다른 요구 사항을 집어넣을 수도 있습니다. 또한 요청 내역을 큐에 저장하거나 로그로 기록할 수 도 있으며, 작업취소 기능도 지원 가능합니다.
본문 예제에서는 리모컨을 이용하여 홈 오토메이션을 구현하는 내용을 다루고 있습니다.
커맨드 객체는 모두 같은 인터페이스를 구현 해야 합니다. 커맨드 메서드이기 때문에 메서드 이름은 excute() 가 적당하겠네요.
0 1 2 3 4 5 6 | package { public interface ICommand { function execute():void } } |
그리고 Light 구상 클래스 입니다. 불을 켜고 끄는 기능이 부여 되어있네요.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 | package { public class Light { public function on():void { trace( "불 켜짐" ) } public function off():void { trace( "불 꺼짐" ) } } } |
다음은 커맨드 인터페이스를 구현하는 LightOnCommand 클래스 입니다.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package { public class LightOnCommand implements ICommand { private var light:Light; public function LightOnCommand( $light:Light ) { this.light = $light; } public function execute():void { light.on(); } } } |
생성자에서 Light 객체를 받아 인스턴스 변수로 저장하고 excute() 가 호출되면 객체 내부의 on() 메서드를 호출 하는 역할을 합니다.
불을 켜고 끄려면 LightOffCommand 클래스도 있어야 겠습니다. 포스트 본문에 보여지지 않는 코드들은 가장 아래에서 다운로드 받을 수 있습니다.
그럼 리모컨 클래스를 살펴보겠습니다.
SimpleRemoteControl 객체는 버튼 하나짜리 리모컨이라고 생각하면 됩니다. 다만 그 버튼에 여러가지 커맨드를 할당하고 해지하면서 기능을 실행 하는 것이죠.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package { public class SimpleRemoteControl { private var slot:ICommand; public function setCommand( $command:ICommand ):void { slot = $command } public function buttonWasPressed():void { slot.execute(); } } } |
불을 켜는 프로세스를 잠깐 살펴보면, Light 객체를 생성자로 받은 LightOnCommand 객체를 다시 SimpleRemoteControl 에서 setCommand() 메서드를 이용해 슬롯에 장전하고, buttonWasPressed() 메서드를 이용해 실행하고 있는거네요.
호스트 코드에서는 이렇게 사용 합니다.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package { import flash.display.Sprite; public class Main extends Sprite { public function Main():void { var remote:SimpleRemoteControl = new SimpleRemoteControl(); var light:Light = new Light(); var garageDoor:GarageDoor = new GarageDoor(); var lightOn:LightOnCommand = new LightOnCommand( light ); var garageOpen:GarageDoorOpenCommand = new GarageDoorOpenCommand( garageDoor ); remote.setCommand( lightOn ); remote.buttonWasPressed(); //출력 : 불 켜짐 remote.setCommand( garageOpen ); remote.buttonWasPressed(); //출력 : 차고 문 열림 } } } |
위에서 설명한대로 호스트 코드에서는 리모컨과 필요한 구상 객체를 만들고 커맨드 객체에 구상 객체를 할당 합니다. 다시 커맨드 객체를 리모컨 객체에 세팅 한 후 커맨드 객체를 실행 하고, 커맨드 객체는 구상 객체의 메서드를 실행하는 구조를 가지고 있습니다. 문장으로 써 놓고 보면 뭔가 복잡해 보이지만 실제로 코드를 실행해 보면 쉽게 이해할 수 있는 구조로 되어 있죠.
요컨대 구상객체에 직접 명령을 내리지 않고, 중간 매개체인 커맨드 객체가 대신 처리하게 하도록 명령을 캡슐화 한 것입니다. 이렇게 하면 호스트 코드에서는 어떤 기능이 리모컨에 할당되어 있는지 관계 없이 명령을 실행할 때는 커맨드 메서드인 excute() 만 호출하면 되겠죠.
Command (simple) Pattern Example 액션스크립트 코드 다운로드 (152)
Blog under the Creative Commons Attribution-NoDerivs 3.0 License