커멘드패턴

임종혁·2024년 12월 18일

개념


  • 어떤 작업을 요청하는 쪽과 처리하는 쪽으로 분리

EX)

음식 주문과정




각 역할


  • 주문서
    • 주문내용을 요구하는 객체
    • 식사 준비에 필요한 행동을 캡슐화한 orderUp() 네소드
    • 이 주문서를 통해 적당한 곳에 메시지 보내기
  • 종업원
    • 주문을 받고, 카운터로 가 orderUp() 호출
    • takeOrder() 메소드에는 여러 고객의 주문서를 매개변수로 전달
  • 주방장
    • 종업원이 orderUp() 메소드 호출시 주방장이 받아서 처리

즉 종업원과 주방장은 주문서로 통신

EX2)

리모컨



커멘드 객체 만들기


1. 커멘드 객체

public interface Command {
	public void excute();
}
  • 여기서 excute는 orderUp에 해당됨

2. 조명을 킬 커멘드 클래스 구현

public class LightOnCommand implements Command {
	Light light;
    
    public LightOnCommand(Light light) {
    	this.light = light;
    }
    
    public void excute() {
    	light.on();
    }
}

3. 리모컨에 커맨드 객체 사용하기

public class SimpleRemoteControl {
	Command slot;
    public SimpleRemoteContol() {}
    
    public void setCommand(Command command) {
    	slot = command;
    }
    
    public void buttonWasPressed() {
    	slot.execute();
    }
}

4. test

public class RemoteContolTest {
	public static void main(String[] args) {
    	SimpleRemoteContol remote = new SmipleRemoteControl();
        Light light = new Light();
        LightOnCommand lightOn = new LightOnCommand(light);
        
        remote.setCommand(lightOn);
        remote.buttonWasPressed();
    }

}
  • simpleRemoteContol = 인보터 = 종업원
  • Light = 리시버 = 요리서 (처리 객체 )
  • LightOnCommand = 커맨드 객체 = 주문서

커맨드 패턴 정의


커맨드 패턴을 사용하면 요청 내역을 객체로 캡슐화 해서 객체를 서로 다른 요청 내역에 따라 매개변수 화 할 수 있음. 이러면 요청을 큐에 저장하거나 로그로 기록하거나 작업 취소 기능을 사용가능함

  • 커맨드 객체는 일련의 행동을 특정 리시버와 연결함으로 요청을 캡슐화 한것

  • 행동과 리시버를 한 객체에 넣고 , excute()라는 메소드 하나만 외부에 공개하는 방법

    • 즉 밖에서 볼땐느 어떤 객체가 리시버 역할을 하는지, 그 리시버가 어떤 일을 하는지 알 수 없음

커맨드 패턴 다이어그램

여러 명령의 리모컨 코드 만들기


public class RemoteControl {
	Command[] onCommands;
    Command[] offCommands;
    
    public RemoteControl() {
    	onCommands = new Command[7];
        offCommands = new Command[7];
        
        Command noCommand = new NoCommand();
        for(int i  =0; i< 7; i++){
        	onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        } 
    }
    
    public void setCommand(int slot, Command onCommand, Command offCommand) {
    	onCommands[slot] = onCommand;
        offCommand[slot] = offCommand;
    }
    
    public void onButtonWasPushed(int slot) {
    	onCommands[slot].excute();
    }
    
    public void offButtonWasPushed(int slot) {
    	offCommands[slot].excute();
    }
    
    pbulic String toString() {
    
    	StringBuffer stringBuff = new StringBuffer();
        StringBuff.append("리모컨");
        for (int i = 0; i < onCommands.length; i++) {
        	stringBuff.append("[slot " + i + "] " + onCommands[i].getClass().getName() + " " + offCommands[i].getClass().getNmae();
        }
        return stringBuff.toString();
    }
}

커맨드 클래스

코드를public class LightOffCommand implements Command {
	Light light;
    
    public LightOnCommand(Light light) {
    	this.light = light;
    }
    
    public void excute() {
    	light.off();
    }
} 입력하세요

테스트

public class RemoteLeader {
    public static void main(String[] args) {
        RemoteControl remoteControl = new RemoteControl();

        Light livingRoomLight = new Light("Living Room");
        Light kitchenLight = new Light("Kitchen");
        CeilingFan ceilingFan = new CeilingFan("Living Room");
        GarageDoor garageDoor = new GarageDoor("Garage");
        Stereo stereo = new Stereo("Living Room");

        LightOnCommand livingRoomLightOn =
                new LightOnCommand(livingRoomLight);
        LightOffCommand livingRoomLightOff =
                new LightOffCommand(livingRoomLight);

        LightOnCommand kitchenLightOn =
                new LightOnCommand(kitchenLight);
        LightOffCommand kitchenLightOff =
                new LightOffCommand(kitchenLight);

        CeilingFanOnCommand ceilingFanOn =
                new CeilingFanOnCommand(ceilingFan);
        CeilingFanOffCommand ceilingFanOff =
                new CeilingFanOffCommand(ceilingFan);

        GarageDoorUpCommand garageDoorUp =
                new GarageDoorUpCommand(garageDoor);
        GarageDoorDownCommand garageDoorDown =
                new GarageDoorDownCommand(garageDoor);

        StereoOnWithCDCommand stereoOnWithCD =
                new StereoOnWithCDCommand(stereo);
        Stereo

NoCommand객체

NoCommand객체는 일종의 널 객체 널 객체는 딱히 리턴할 것도 없고 클라이언트가 null을 처리하지 않게 하고 싶을때 활용하면 좋습니다. 널 객체는 여러 디자인 패턴에서 유용하게 쓰임 널객체를 일종의 디자인 패턴이라고도 부름

커맨드 패턴 활용


  • 커맨드로 컴퓨테이션의 한 부분을 패키지로 묶어 일급 객체 형태로 전달
  • 커맨드 패턴을 스케줄러나 스레드풀, 작업큐 와 같은 다양한 작업에 사용할 수 있음
  • 스레드는 excute메소드를 호출하고 호출이 완료되면 커맨드 객체를 버리고 새로운 커맨드 객체를 가져옴

0개의 댓글