6. 커맨드 패턴

  1. 6. 커맨드 패턴
    1. 1. 요구사항
    2. 2. 문제점 및 해결책
    3. 3. 객체 생성하기
    4. 4. 커맨드패턴
    5. 5. 리모컨 코드
    6. 6.undo 기능추가
    7. 7.리모컨에 파티모드
    8. 문서에 대하여

1. 요구사항

  • 리모컨 제작요청
  • 리모컨에는 일곱가지프로그래밍이 가능한 슬롯과 각 슬롯에 온/오프스위치
  • 각 슬롯은 서로 다른 가정용 기기에 연결할 수 있다.
  • 조명, 팬, 욕조, 오디오를 비롯한 각종 홈오토메이션 장비 제어를 위한 각 업체로 부터 공급 받은 자바클래스
  • 리모컨 프로그래밍을 위한 API제작 요청

2. 문제점 및 해결책

2.1 문제점

  • 모든 클래스마다 on(), off()는 물론이고 dim(),setTemperature(), setVolume(), setDiredtion()등의 메소드가 존재
  • 향후 다른 제품이 추가되면 다른 이름을 가진 메소드가 추가될 가능성 존재
  • 리모컨 API입장에서 lingt.on(), hottub.jetsOn()을 호출하지 말고 어느 정도 추상화 시킬 필요존재

2.2 해결책

  • 커맨드 패턴 사용시 작업을 요청한 쪽과 그 작업을 처리한쪽을 분리 시킬수 있다.
  • 리모컨에서는 작업을 요청하고, 업체에서 공급한 클래스에서 그작업을 수행한다.

3. 객체 생성하기

3.1 Command 인터페이스 만들기


public interface Command{
	public void execute();
}

3.2 전등을 켜기 위한 커맨드 클래스 구현


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

3.3 커맨드 객체 사용하기


public class SimpleRemoteControl{
	Command slot;
	
	public SimpleRemoteControl(){}

	public void setCommand(Command command){
		slot = command;
	}

	public void buttonWasPressed(){
		slot.execute();
	}
}

3.4 리모컨을 사용하기 위한 간단한 테스트 클래스


public class RemoteControlTest{
	public static void main(String[] agrs){
		SimpleRemoteControlremote remote = new SimpleRemoteControl();
		Light light = new Light();
		LightOnCommand lightOn = new LightOnCommand(light);

		remote.setCommand(lightOn);
		remote.butonWasPressed();
	}
}

4. 커맨드패턴

  • 정의 : 커맨드패턴을 이용하면 요구사항을 객체로 캡슐화 할수 있으며, 매개변수를 써서 여러가지 다른 요구사항을
    집어넣을 수도 있습니다. 또한 요청내역을 큐에 저장하거나 로그로 기록할 수도 있으며, 작업취소 기능도 지원 가능합니다.
  • 특징
    1. 일련의 행동을 특정 리시버하고 연결을 통해 캡슐화한다.
    2. execute()라는 메소드 하나만 외부에 공개한다.

5. 리모컨 코드


public class RemoteControl{
	Command[] onCommands;
	Command[] offCommands;

	public RemoteControl(){
		onCommands = new Commnad[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 offCommnad){
		onCommands[slot] = onCommand;
		offCommands[slot] = offCommand;
	}

	public void onButtonWasPushed(int slot){
		onCommands[slot].execute();
	}
	
	public void offButtonWasPushed(int slot){
		offCommands[slot].execute();
	}

	public String toString(){
		StringBuffer stringBuff = new StringBuffer();
		stringBuff.append("\n-------Remote Control ------\n");
		for(int i=0l i<onCommands.lentgh; i++){
			stringBuffer.append("[slot " + i + "]" + onCommands[i].getClass().getName()
				+ "    " +  offCommands[i].getClass().getName() + "\n");
		}	
		return stringBuff.toString();
	}
}


public class StereoOnWithCDCommand implements Command{
	Stereo stereo;

	public StereoOnWithCDCommand(Stereo stereo){
		this.stereo = stereo;
	}

	public void execute(){
		stereo.on();
		stereo.setCD();
		stereo.setVolume(11);
	}
}

6.undo 기능추가

6.1 Command 인터페이스 만들기


public interface Command{
	public void execute();
	public void undo();
}

6.2 전등을 켜기 위한 커맨드 클래스 구현


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

	public void undo(){
		light.off();
	}
}

6.3 전등을 끄기 위한 커맨드 클래스 구현


public class LightOffCommand implements Command{
	Light light;
	
	public LightOffCommand(Light light){
		this.light = light;
	}
	
	public void execute(){
		light.off();
	}

	public void undo(){
		light.on();
	}
}

6.4 리모컨 undo


public class RemoteControl{
	Command[] onCommands;
	Command[] offCommands;
	Command undoCommand;

	public RemoteControl(){
		onCommands = new COmmnad[7];
		offCOmmands = new Command[7];

		Command noCommand = new noCommand();
		for(int i=0; i<7; i++){
			onCommands[i] = noCommand;
			offCommands[i] = noCommand;
 		}
		undoCommand = noCommand;
	}

	public void setCommand(int slot, Command onCommand, Command offCommnad){
		onCommands[slot] = onCommand;
		offCommands[slot] = offCommand;
	}

	public void onButtonWasPushed(int slot){
		onCommands[slot].execute();
		undoCommand = onCommand[slot];
	}
	
	public void offButtonWasPushed(int slot){
		offCommands[slot].execute();
		undoCommand = offCommand[slot];
	}

	public void undoButtonWasPushed(){
		undoCommand.undo();
	}

	public String toString(){
		StringBuffer stringBuff =new StringBuffer();
		stringBuff.append("\n-------Remote Control ------\n");
		for(int i=0l i<onCommands.lentgh; i++){
			stringBuffer.append("[slot " + i + "]" + onCommands[i].getClass().getName()
				+ "    " + + offCommands[i].getClass().getName() + "\n");
		}	
		return stringBuff.toString();
	}
}

7.리모컨에 파티모드

버튼 한 개만 누루면 전등이 어두워지면서 오디오, TV가 켜지고, DVD모드로 변경되고, 욕조에 물이 채워지는것까지 한번에 켜지는 기능?


public class MacroCommand impelnets Command{
	Commnad[] commands;

	public MacroCommand(Commnad[] commands){
		this.commands = commands;
	}
	
	public void execute(){
		for(int i=0; i<commdands.lentth; i++){
			commands[i].execute();
		}
	}
}


public class party{
	Light light = new Light("living Room");
	TV tv = new TV("Living Room");
	Stereo stereo = new stereo("Living Room");
	Hottbu hottub = new Hottub();

	LightOnCommand lightOn = new LightOnCOmmand(light);
	StereoOnCommand stereoOn = new StereoOnCommand(stereo);
	TVOnCommand tvOn = new VTOnCommnad(tv);
	HottubOnCommand hottubOn = new HottubOnCommand(hottub);

	Command[] partyOn = {lightOn, stereoOn, tvOn, hottubOn};
	Commnad[] partyOff = {lightOff, stereoOff, tvOff, hottubOff};

	MacroCommand partyOnMacro = new MacroCommand(partyOn);
	MacroCommand partyOffMacro = new MacroCommand(partyOff);

	remotoCOntrol.setCommand(0, partyOnMarco, partyOffMacro);
}

문서에 대하여