본문 바로가기

Backend/Java Design Pattern

[JAVA 디자인 패턴] 커맨드 패턴 (Command Pattern) 활용 1

728x90

연습문제 1. TwoButtonController 클래스를 구현. 

 

* 기존코드

class TwoButtonController{
	private TV tv;

	public TwoButtonController(TV tv) {
		this.tv = tv;
	}
	
	public void button1Pressed() {
		tv.power();
	}
	public void button2Pressed() {
		tv.mute();
	}
}
class TV{
	private boolean powerOn = false;
	private boolean muteOn =false;
	
	public void power() {
		powerOn =! powerOn;
		if(powerOn) {
			System.out.println("power on");
		} else {
			System.out.println("power off");
		}
	}
	public void mute() {
		if(!powerOn)	return;
		
		muteOn =! muteOn;
		if(muteOn) {
			System.out.println("mute on");
		} else {
			System.out.println("mute off");
		}
	}
}

 

* 다음 요구사항을 충족할 수 있도록 TwoButtonController 클래스를 개선하라.

 

 1) TwoButtonController 클래스를 이용해 TV전원과 음소거를 제어할 수 있다.

 2) TwoButtonController 클래스의 각 버튼을 눌렀을 때 실행되는 기능은 전원과 음소거 중에서 임의의 방식으로 결정 할 수 있다. 버튼이 2개 (button1, button2) 고 동작할 수 있는 기능이 2가지(전원, 음소거)이므로 4가지 조합이 가능해야 한다. 

3) TwoButtonController 클래스는 각 버튼을 눌렀을 때 동작하는 기능을 변경할 수 있어야 한다. 그러나 TwoButtonController 클래스의 코드가 변경되지 않도록 해야 한다. 

 

 


 * 코드 구현

* Command.java

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

 

* PowerOnCommand.java

public class PowerOnCommand implements Command {
	private PowerButton powerbutton;

	public PowerOnCommand(PowerButton powerbutton) {
		this.powerbutton = powerbutton;
	}

	@Override
	public void execute() {
		powerbutton.powerOn();
	}

}

 

* PowerOffCommand.java

public class PowerOffCommand implements Command {
	private PowerButton powerbutton;

	public  PowerOffCommand(PowerButton powerbutton) {
		this.powerbutton = powerbutton;
	}

	@Override
	public void execute() {
		powerbutton.powerOff();
	}

}

 

* MuteOnCommand.java

public class MuteOnCommand implements Command {
	private MuteButton mutebutton;

	public MuteOnCommand(MuteButton muteButton) {
		this.mutebutton = muteButton;
	}

	@Override
	public void execute() {
		mutebutton.muteOn();
	}

}

 

* MuteOffCommand.java

public class MuteOffCommand implements Command {
	private MuteButton mutebutton;

	public MuteOffCommand(MuteButton muteButton) {
		this.mutebutton = muteButton;
	}

	@Override
	public void execute() {
		mutebutton.muteOff();
	}

}

 

* PowerButton.java

class PowerButton {
	public void powerOn() {
		System.out.println("power on");
	}

	public void powerOff() {
		System.out.println("power off");
	}
}

 

* MuteButton.java

class MuteButton {
	public void muteOff() {
		System.out.println("mute off");
	}

	public void muteOn() {
		System.out.println("mute on");
	}
}

 

* TwoButtonController.java

//그대로 있어야 되는 코드. 변경은 Concrete Command 에서 진행된다. 
public class TwoButtonController {
	private Command powerCommand;
	private Command muteCommand;
	
	public TwoButtonController(Command firstCommand,Command secondCommand) {
		setCommand(firstCommand, secondCommand);
	}
	
	public void setCommand(Command firstCommand,Command secondCommand) {
		this.powerCommand = firstCommand;
		this.muteCommand = secondCommand;
	}
	
	public void powerBtnPressed() {
		powerCommand.execute();
	}
	
	public void muteBtnPressed() {
		muteCommand.execute();
	}
}

 

* 실행할 Main클래스

public class Main {
	
	public static void main(String[] args) {
		PowerButton powerButton = new PowerButton();
		MuteButton muteButton = new MuteButton();
		
		Command powerOnButton = new PowerOnCommand(powerButton);
		Command powerOffButton = new PowerOffCommand(powerButton);
		Command muteOnButton = new MuteOnCommand(muteButton);
		Command muteOffButton = new MuteOffCommand(muteButton);
		
		//4가지의 경우의 만들기.
		TwoButtonController btn1 = new TwoButtonController(powerOnButton,muteOnButton);
		
		btn1.powerBtnPressed();
		btn1.muteBtnPressed();
		
		btn1.setCommand(powerOffButton, muteOffButton);
		btn1.powerBtnPressed();
		btn1.muteBtnPressed();
		
		btn1.setCommand(powerOnButton, muteOffButton);
		btn1.powerBtnPressed();
		btn1.muteBtnPressed();
		
		btn1.setCommand(powerOffButton, muteOnButton);
		btn1.powerBtnPressed();
		btn1.muteBtnPressed();
	}
}

UML 구조는 다음과 같다.

UML


 

 

하지만 이방식은 TV라는 recevier 로 받지 않고, TwoButtonController 에 대해서 변경사항이 생길 수 있는 코드 이기 때문에 완벽한 설계가 아니다. 버튼 자체를 관리하지않고, TV로 관리를 하는 것이다. 

 다음 문제를 해결하자면 이렇다.

 

* 코드구현

 

class TV{
	private boolean powerOn = false;
	private boolean muteOn = false;
	
	public void power() {
		powerOn =! powerOn;
		if(powerOn) {
			System.out.println("power on");
		} else {
			System.out.println("power off");
		}
	}
	public void mute() {
		if(!powerOn)	return;
		
		muteOn =! muteOn;
		if(muteOn) {
			System.out.println("mute on");
		} else {
			System.out.println("mute off");
		}
	}
}

interface Command {
	public abstract void execute();
}

class PowerCommand implements Command {
	private TV tv;

	public PowerCommand(TV tv) {
		this.tv = tv;
	}

	@Override
	public void execute() {
		tv.power();
	}

}

class PowerOffCommand implements Command {
	private PowerButton powerbutton;

	public  PowerOffCommand(PowerButton powerbutton) {
		this.powerbutton = powerbutton;
	}

	@Override
	public void execute() {
		powerbutton.powerOff();
	}

}

class MuteCommand implements Command {
	private TV tv;
	

	public MuteCommand(TV tv) {
		this.tv = tv;
	}

	@Override
	public void execute() {
		tv.mute();
	}

}

class PowerButton {
	public void powerOn() {
		System.out.println("power on");
	}

	public void powerOff() {
		System.out.println("power off");
	}
}

class MuteButton {
	public void muteOff() {
		System.out.println("mute off");
	}

	public void muteOn() {
		System.out.println("mute on");
	}
}

//그대로 있어야 되는 코드. 변경은 Concrete Command 에서 진행된다. 
class TwoButtonController {
	private Command command1;
	private Command command2;
	
	public void setCommand(Command command1,Command command2) {
		this.command1 = command1;
		this.command2 = command2;
	}
	
	public void button1Pressed() {
		command1.execute();
	}
	
	public void button2Pressed() {
		command2.execute();
	}
}

public class Main {
	
	public static void main(String[] args) {
		TV tv = new TV();
		TwoButtonController rc = new TwoButtonController();
		Command powerCommand = new PowerCommand(tv);
		
		//2개의 버튼에 동일한 powerCommand 객체를 전달함.
		rc.setCommand(powerCommand, powerCommand);
		
		rc.button1Pressed();
		
		//button2, button1은 동일한 powerCommand 객체를 공유한다.
		rc.button2Pressed(); //off
		rc.button1Pressed();
		rc.button1Pressed();
		rc.button2Pressed();
		rc.button1Pressed();
		rc.button1Pressed();
		
		System.out.println();
		Command muteCommand = new MuteCommand(tv);
		rc.setCommand(powerCommand, muteCommand );
		rc.button2Pressed(); //off
		rc.button1Pressed();
		rc.button1Pressed();
		rc.button2Pressed();
		rc.button1Pressed();
	}
}

 

UML 구조는 다음과 같다.

UML

 

 

728x90