Command Pattern
Behavioral Pattern
Intro
데이터 기반의 설계 패턴
요청을 객체로 캡슐화하여 다른 요청, 대기열 또는 로그 요청으로 클라이언트를 매개 변수화하고 실행 취소 가능한 작업을 지원할 수 있다.
객체에 대한 메서드 호출을 전체 객체 상태로 관리
객체 지향 콜백
구성
Receiver 클래스는 요청을 시작하는 책임을 갖는 클래스이다.
해당 클래스에는 명령 개체에 대한 참조를 저장하기 위한 필드가 있어야 한다.
발신자는 요청을 수신자에게 직접 보내는 대신 해당 명령을 트리거한다.
보낸 사람은 명령 개체를 생성할 책임이 없다.
일반적으로 생성자를 통해 클라이언트에서 미리 생성된 명령을 받는다.
Command 인터페이스는 일반적으로 명령을 실행하기 위한 단 하나의 방법을 선언한다.
Concrete Command는 다양한 종류의 요청을 구현한다.
구체적인 명령은 자체적으로 작업을 수행하는 것이 아니라 비즈니스 논리 개체 중 하나에 호출을 전달하도록 되어 있다.
그러나 코드를 단순화하기 위해 이러한 클래스를 병합할 수 있다.
수신 개체에서 메서드를 실행하는 데 필요한 매개 변수는 구체적인 명령에서 필드로 선언할 수 있다.
생성자를 통해서만 이러한 필드의 초기화를 허용함으로써 명령 객체를 변경 불가능하게 만들 수 있다.
Receiver 클래스는 어떤 비즈니스 로직을 포함하고 있다.
거의 모든 객체가 수신자의 역할을 할 수 있다.
대부분의 명령은 요청이 수신자에게 전달되는 방법에 대한 세부사항만 처리하고 수신자 자체가 실제 작업을 수행한다.
Client 는 구체적인 명령 객체를 작성하고 구성한다.
클라이언트는 수신자의 인스턴스를 포함한 모든 요청 매개 변수를 명령의 생성자에 전달해야 한다.
그 후 결과 명령은 하나 또는 여러 발신자와 연관될 수 있다.
구현 방법
단일 실행 방법으로 명령 인터페이스를 선언한다.
명령 인터페이스를 구현하는 구체적인 명령 클래스로 요청 추출을 시작한다.
각 클래스에는 실제 수신자 객체에 대한 참조와 함께 요청 인수를 저장하기 위한 필드 세트가 있어야 한다.
이러한 모든 값은 명령의 생성자를 통해 초기화되어야 한다.
발신자 역할을 할 클래스를 식별한다.
이러한 클래스에 명령을 저장하기 위한 필드를 추가한다.
발신자는 명령 인터페이스를 통해서만 명령과 통신해야 한다.
발신자는 일반적으로 자체적으로 명령 개체를 생성하지 않고 클라이언트 코드에서 가져온다.
수신자에게 직접 욫어을 보내는 대신 명령을 실행하도록 송신자를 변경한다.
클라이언트는 다음 순서로 개체를 초기화 해야 한다.
수신자를 만든다.
명령을 작성하고 필요한 경우 수신자와 연관시킨다.
보낸 사람을 만들고 특정 명령과 연결한다.
장점
SRP: 이러한 작업을 수행하는 클래스에서 작업을 호출하는 클래스를 분리할 수 있다.
OCP: 기존 클라이언트 코드를 손상시키지 않고 앱에 새 명령을 도입할 수 있다.
실행 취소, 다시 실행 기능을 구현할 수 있다.
지연된 작업 실행을 구현할 수 있다.
간단한 명령 세트를 복잡한 명령으로 조합할 수 있다.
단점
발신자와 수신자 사이에 새로운 레이어를 도입하는 것이기 때문에 코드가 복잡해 질 수 있다.
Command 패턴이 필요한 상황
작업으로 개체를 매개변수화하기 위해서 명령 패턴을 사용한다.
명령 패턴은 메서드 호출을 독립 실행형 개체로 바꿀 수 있다.
명령을 메서드 인수로 전달하고, 다른 개체에 저장하고, 런타임에 연결된 명령을 전환할 수 있다.
작업을 대기열에 추가하거나 실행을 예약하거나 원격으로 실행하기 위해서 명령 패턴을 사용한다.
명령을 직렬화 하여 파일이나 데이터베이스에 쉽게 쓸 수 있는 문자열로 변환할 수 있다.
나중에 문자열을 초기 명령 개체로 복원할 수 있다.
따라서 명령 실행을 지연하고 예약할 수 있다.
네트워크를 통해 명령을 대기열에 추가하거나 기록하거나 전송할 수 있다.
실행 취소 및 다시 실행에 대한 구현 방법이 여러 가지 방법이 있지만 명령 패턴이 가장 많이 사용된다.
작업을 되돌릴 수 있는 기능을 구현하기 위해서는 작업의 기록을 관리하는 기능이 필요하다.
명령의 기록은 애플리케이션 상태의 관련 백업과 함께 실행된 모든 명령 개체를 포함하는 스택형태 이다.
이 방법에는 두 가지 단점이 있다.
첫번재는 응용 프로그램의 상태 중 일부는 비공개 일 수 있으므로 저장하기 쉽지 않다.
하지만 memento pattern 을 통해 완화할 수 있다.
두 번째는 상태 백업은 많은 메모리를 소비할 수 있다.
따라서 대체 구현에 의지할 수 있다.
과거 상태를 복원하는 대신 명령이 역 연산을 수행한다.
리버스 오퍼레이션에도 대가를 따른다.
구현이 어렵거나 불가능할 수 있다.
Java API
java.lang.Runnable 인터페이스가 스레드에 의해 실행되는 클래스에 의해 구현된 인터페이스를 정의한다.
javax.swing.Action도 명령 패턴을 따른다.
주의사항
명령 패턴은 수행할 작업으로 객체를 매개 변수화하므로 절차 언어의 콜백 함수와 동일하다.
명령 개체는 나중에 실행하기 위해 대기열에 넣을 수 있다.
명령 인터페이스는 unexecute 메서드의 동작을 반대로 하는 메서드 execute를 도입할 수 있다.
실행된 명령은 목록에 저장될 수 있으며 실행 또는 실행 취소를 호출하는 동안 목록의 앞 뒤로 순회하면 각각 다시 실행 및 실행 취소를 지원할 수 있다.
memento 패턴을 통해 명령을 취소해야 하는 상태를 기억할 수 있다.
명령 인터페이스는 명령 로깅을 허용하는 디스크에서 저장하고 읽는 방법을 추가할 수 있다.
충돌이 발생한 경우 로그를 읽고 명령을 동일한 순서로 다시 실행하여 시스템을 충돌 직전 상태로 되돌릴 수 있다.
명령 패턴은 트랜잭션을 모델링하는 방법을 제공한다.
트랜잭션은 데이터에 적용되는 세분화된 작업으로 구성된다.
Last updated