You will be fine

<디자인패턴입문> 19. Command 패턴

by BFine
반응형

www.yes24.com/Product/Goods/2918928

 

Java 언어로 배우는 디자인 패턴 입문

이 책은 디자인 패턴의 입문서입니다. GoF가 정리한 23개의 디자인 패턴을 하나씩 다루면서 객체 지향을 잘 모르는 초보자도 이해하기 쉽도록 정리하고 있습니다. 단순한 이론이나 논리을 제시하

www.yes24.com

 

가. 무엇인가

 a. 명령 하달

  - 실행하고 싶은 일을 메서드 호출하는 동적인 처리로 하는 것이 아니라 클래스의 인스턴스로 표현한다.

  -  Command는 Event(사건)라고도 부르며 이벤트 처리 프로그래밍에서 사용되는 이벤트와 같은 의미이다.

     => 이벤트를 하나의 인스턴스로 보고 예를들어 마우스 클릭 등을 발생 순서대로 처리하는 프로그래밍

 

나. 만든 예제

위치를 명령으로 이동시키는 예제

 a. Command(명령)의 역할

  -  명령을 정의하는 인터페이스,  ConcreteCommand를 하나로 묶는 역할을 한다.

public interface Command {
    Position execute(int x, int y);
}

 b. ConcreteCommand(구체적인 명령)의 역할

  -  예제에서는 위치를 이동시키는 명령들이 이 역할을 하고 있다.

public class DownCommand implements Command {

    private final Receiver receiver;

    public DownCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public Position execute(int x, int y) {
        return receiver.down(x,y);
    }
}

public class LeftCommand implements Command {
    private final Receiver receiver;

    public LeftCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public Position execute(int x, int y) {
        return receiver.left(x,y);
    }
}

public class RightCommand implements Command {
    private final Receiver receiver;

    public RightCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public Position execute(int x, int y) {
        return receiver.right(x,y);
    }
}


public class UpCommand implements Command {
    private final Receiver receiver;

    public UpCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public Position execute(int x, int y) {
        return receiver.up(x,y);
    }
}


 c. Receiver(수신자)의 역할

  -  Command 역할이 명령을 실행할때 대상이 되는 역할을 한다.

      => 명령을 받아들이는 수신자

  -  Command 클래스 다이어그램에는 Receiver에 대한 인터페이스를 구현하지 않지만 만들어보았다.

public interface Receiver {
    Position up(int x, int y);
    Position down(int x, int y);
    Position left(int x, int y);
    Position right(int x, int y);
}


public class MoveReceiver implements Receiver {
    @Override
    public Position up(int x, int y) {
        int dx = x-1;
        if(isRange(dx)){
            return new Position(dx,y);
        }
        return new Position(x,y);
    }

    @Override
    public Position down(int x, int y) {
        int dx = x+1;
        return new Position(dx,y);
    }

    @Override
    public Position left(int x, int y) {
        int dy = y-1;
        if(isRange(dy)){
            return new Position(x,dy);
        }
        return new Position(x,y);
    }

    @Override
    public Position right(int x, int y) {
        int dy = y+1;
        return new Position(x,dy);
    }

    private boolean isRange(int d){
        return d >= 0;
    }
}

 d. Invoker(기동자)의 역할

  -  명령의 행동을 개시하는 역할 즉 Command 역할의 인터페이스를 호출하는 역할을 한다.

public class MoveInvoker {
    private Queue<Command> queue;

    public MoveInvoker() {
        this.queue = new LinkedList<>();
    }
    public void addCommand(Command command){
        this.queue.add(command);
    }

    public Position execute(int x, int y){
        while (!queue.isEmpty()){
            Command command = queue.poll();
            Position newPosition = command.execute(x, y);
            x = newPosition.getX();
            y = newPosition.getY();
        }
        return new Position(x,y);
    }
}

 e. Main(Client)

package command;

import command.cmd.*;
import command.receiver.MoveReceiver;

import java.util.Arrays;

public class Main {
    public static int[][] map;

    public static void main(String[] args) {
        map = new int[5][5];
        int startX = 0,startY = 0;
        MoveInvoker moveInvoker = new MoveInvoker();
        Command up = new UpCommand(new MoveReceiver());
        Command down = new DownCommand(new MoveReceiver());
        Command left = new LeftCommand(new MoveReceiver());
        Command right = new RightCommand(new MoveReceiver());

        moveInvoker.addCommand(down);
        moveInvoker.addCommand(right);
        moveInvoker.addCommand(down);
        moveInvoker.addCommand(right);
        moveInvoker.addCommand(down);
        moveInvoker.addCommand(left);
        moveInvoker.addCommand(right);
        moveInvoker.addCommand(up);

        map[startX][startY] = 1;
        Position execute = moveInvoker.execute(startX, startY);
        map[execute.getX()][execute.getY()] = 2;
        print();

    }

    private static void print(){
        for (int[] arr: map) {
            System.out.println(Arrays.toString(arr));
        }
        System.out.println();
    }
}

/*

"C:\Program Files\Java\jdk1.8.0_251\bin\java.exe"
[1, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 2, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]

*/

  

다. 정리

 a. 이력의 저장

  -  이동하는 부분을 인스턴스로 표현했기 때문에 이 인스턴스를 파일로 저장한다면 이동이력을 저장할 수 있다.

Command 패턴은 명령을 인스턴스화 시키고 하나의 집합처럼 다루는 패턴이다.

 

반응형

블로그의 정보

57개월 BackEnd

BFine

활동하기