반응형

: 일련의 행동을 특정 리시버(받는자)와 연결시킴으로써 요구사항을 캡슐화 한 것.

 

 

배우게 될 내용.

- 메소드 호출을 캡슐화

- 캡슐화된 메소드 재사용

 

 

가정) 최신형 리모컨을 개발한다. 리모컨 안에는 일곱 가지 프로그래밍이 가능한 슬롯이 있습니다.

그 일곱 가지를 가지고 on / off 할 수 있는 스위치도 가지고 있습니다.

뭐.. 대충 이렇게 생겼다.

기능에 대해 얘기해보자면, 스마트홈 같은 집에 불켜기, 가스불 끄기, 욕조물 데우기 등의 기능이 있다고 치겠습니다.

이러한 메소드들을 캡슐화하고, 캡슐화된 메소드를 재사용 해보겠습니다.

 

 

예제 작성 1

:  리모컨 버튼이 하나만 있다고 생각하고 불을 키는 버튼을 가진 리모컨을 사용해 커맨드 패턴을 사용하겠습니다.

 

//커맨드 객체
public interface Command {
    //실행 메소드
    void execute();
}


//불을 키는 클래스
public class LightOnCommand implements Command {
    Light light;

    public  LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }
}
//불
public class Light {

    // 켜짐
    public String on() {
        Log.d("abcd", "불 켜짐");
        return "불 켜짐";
    }

    // 꺼짐
    public String off() {
        return  "불 꺼짐";
    }
}


//불을 키는 클래스
public class LightOnCommand implements Command {
    Light light;

    public  LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }
}
//리모컨
public class RemoteController {
    Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void buttonClicked() {
        command.execute();
    }
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //리모컨 객체 생성
        RemoteController remoteCon = new RemoteController();
        // 불빛 객체
        Light light = new Light();
        // 불 키는 명령을 내리는 command 객체에 넣어줌
        LightOnCommand lightOn = new LightOnCommand(light);
        // command 설정
        remoteCon.setCommand(lightOn);
        // 클릭
        remoteCon.buttonClicked();

    }
}

결관 ; D/abcd: 불 켜짐

.

.

 

커맨드 패턴 : 커맨드 패턴을 이용하면 요구사항을 객체로 캡술화 할 수 있으며, 매개변수를 써서 여러가지 다른 요구사항을 집어 넣을 수도 있습니다. 또한 요청 내역을 큐(queue)에 저장하거나 로그로 기록할 수 있으며, 작업취소 기능도 지원 가능합니다.

.

.

.

.

.

 

갖가지 기능들을 추가하도록 하겠습니다.

.

.

.

바뀐 부분.

//null 방지를 위해 넣어줌.
public class NoCommand implements Command {
    @Override
    public void execute() {
        Log.d("abcd", "null 방지");
    }
}

 noCommand 객체는 일종의 null객체입니다. 리턴할 객체는 없지만,

클라이언트 쪽에서 null을 처리하지 않아도 되도록 하고 싶을 때 null 객체를 활용하면 좋습니다.

(즉, 빈자리를 채우기 위한 용도일 뿐입니다.)

//커맨드 객체
public interface Command {
    //실행 메소드
    void execute();
    //취소 메솓,
    void undo();
}
//리모컨
public class RemoteController {
    Command[] onCommands;
    Command[] offCommands;
    Command undoCommand;

    public RemoteController() {
        // 7개의 기능을 가진 버튼 on/off을 실행할 array[]
        onCommands = new Command[7];
        offCommands = new Command[7];

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

    //command 설정
    public void setCommand(int slot, Command onCommand, Command offCommand) {
        this.onCommands[slot] = onCommand;
        this.offCommands[slot] = offCommand;
    }

    //on 버튼 클릭
    public void onButtonClicked(int slot) {
        this.onCommands[slot].execute();
        //실행 후, 실행 취소를 누르면 바로 취소시키기 위해 해당 버튼의 [slot]을 준비시킴
        undoCommand = onCommands[slot];
    }

    //off 버튼 클릭
    public void offButtonClicked(int slot) {
        this.offCommands[slot].execute();
        undoCommand = offCommands[slot];
    }
    //취소 버튼 클릭
    public void undoButtonClicked() {
        undoCommand.undo();
    }
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //리모컨 객체 생성
        RemoteController remoteCon = new RemoteController();
        // 불빛 객체
        Light light = new Light();

        // 불 키는 명령
        LightOnCommand lightOn = new LightOnCommand(light);
        // 불 끄는 명령
        LightOffCommand lightOff = new LightOffCommand(light);

        // command 설정
        remoteCon.setCommand(0,lightOn,lightOff);

        // 클릭
        remoteCon.onButtonClicked(0);
        remoteCon.offButtonClicked(0);
        remoteCon.undoButtonClicked();

    }
}

 

 


 

코틀린 코드

interface Command  {
    fun execute()
    fun undo()
}

//
class LightOnCommand constructor(light: Light) :Command {

    var light : Light? = null

    init {
        this.light = light
    }

    override fun execute() { light?.on() }

    override fun undo() { light?.off() }
}


//
class LightOffCommand constructor(light:Light) : Command {

    var light : Light? = null
    init {
        this.light = light
    }

    override fun execute() {
       light?.off()
    }

    override fun undo() {
        light?.on()
    }
}


///
class NoCommand : Command {
    override fun execute() {
        TODO("Not yet implemented")
    }

    override fun undo() {
        TODO("Not yet implemented")
    }
}
class Light {
    fun on() { Log.d("abcd", "불 켜기")}
    fun  off() {Log.d("abcd","불끄기")}
}
class RemoteController {
     var onCommand: Array<Command>? = null
     var offCommand: Array<Command>? = null
    var undoCommand:Command? = null

    init {
        val noCommand = NoCommand()
        //사이즈, 초기화
        onCommand =Array(7, {noCommand})
        offCommand = Array(7, {noCommand})

        undoCommand = noCommand
    }

    fun setCommand(slot:Int, onCommand: Command, offCommand: Command) {
        this.onCommand?.set(slot, onCommand)
        this.offCommand?.set(slot, offCommand)
    }

    fun onButtonClicked(slot:Int) {
       this.onCommand?.get(slot)!!.execute()
        undoCommand = onCommand!![slot]
    }

    fun offButtonClicked(slot:Int) {
        this.offCommand?.get(slot)!!.execute()
        undoCommand = offCommand!![slot]
    }

    fun undoButtonClicked() {
        undoCommand!!.undo()
    }

}
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)


        val remoteCon = RemoteController()
        val light:Light = Light()

        var lightOn: LightOnCommand = LightOnCommand(light)
        var lightOff: LightOffCommand = LightOffCommand(light)

        remoteCon.setCommand(0,lightOn,lightOff)

        remoteCon.onButtonClicked(0)
        remoteCon.offButtonClicked(0)
        remoteCon.undoButtonClicked()

    }
}

 

 

 

 

 

 

반응형

+ Recent posts