검수요청.png검수요청.png

"커맨드패턴"의 두 판 사이의 차이

해시넷
이동: 둘러보기, 검색
(참고자료)
1번째 줄: 1번째 줄:
'''커맨드패턴'''(Command pattern)이란?
+
'''커맨드패턴'''<!--커맨드패턴-->(Command pattern)은 요청을 객체의 형태로 캡슐화하여 사용자가 보낸 요청을 나중에 이용할 수 있도록 매서드 이름, 매개변수 등 요청에 필요한 정보를 저장 또는 로깅, 취소할 수 있게 하는 패턴이다.<ref name="커맨드패턴">〈[https://ko.wikipedia.org/wiki/%EC%BB%A4%EB%A7%A8%EB%93%9C_%ED%8C%A8%ED%84%B4 커맨드 패턴]〉, 《위키백과》</ref>
 +
 
 +
 
 +
 
 +
== 특징 ==
 +
커맨드 패턴에는 명령(command), 수신자(receiver), 발동자(invoker), 클라이언트(client)의 네개의 용어가 항상 따른다. 커맨드 객체는 수신자 객체를 가지고 있으며, 수신자의 메서드를 호출하고, 이에 수신자는 자신에게 정의된 메서드를 수행한다. 커맨드 객체는 별도로 발동자 객체에 전달되어 명령을 발동하게 한다. 발동자 객체는 필요에 따라 명령 발동에 대한 기록을 남길 수 있다. 한 발동자 객체에 다수의 커맨드 객체가 전달될 수 있다. 클라이언트 객체는 발동자 객체와 하나 이상의 커맨드 객체를 보유한다. 클라이언트 객체는 어느 시점에서 어떤 명령을 수행할지를 결정한다. 명령을 수행하려면, 클라이언트 객체는 발동자 객체로 커맨드 객체를 전달한다. <ref name = "커맨드패턴" />
 +
 
 +
[[파일:커맨드패턴클래스.png|700픽셀|가운데|섬네일|커맨드 패턴 클래스 다이어그램]]
 +
 
 +
== 예시 ==
 +
* 만능 버튼 만들기 : 버튼이 눌리면 램프의 불이 켜지는 프로그램 <ref name="커맨드패턴예시">〈[https://gmlwjd9405.github.io/2018/07/07/command-pattern.html 커맨드 패턴예시]〉, 《Design Pattern》</ref>
 +
 
 +
  public class Lamp {
 +
  public void turnOn(){ System.out.println("Lamp On"); }
 +
  }
 +
  public class Button {
 +
  private Lamp theLamp;
 +
  public Button(Lamp theLamp) { this.theLamp = theLamp; }  // 버튼 클래스의 생성자를 이용해 불을 켤 램프의 객체를 전달한다.
 +
  public void pressed() { theLamp.turnOn(); }
 +
  } <br>
 +
  public class Client {
 +
  public static void main(String[] args) {
 +
    Lamp lamp = new Lamp(); 
 +
    Button lampButton = new Button(lamp);  // 버튼 클래스의 pressed가 호출되면 생성자를 통해 전달받은 램프 객체의 turnOn()을 호출해 불을 켠다.
 +
    lampButton.pressed();
 +
  }
 +
  }
 +
 
 +
=== 문제점 ===
 +
* 버튼을 눌렀을 때 다른 기능을 실행하는 경우<ref name="커맨드패턴예시" />
 +
 
 +
:{|class=wikitable width=850 style="background-color:#ffffee"
 +
|-
 +
!align=center style="background-color:#ffeecc"|궁금점
 +
!align=center style="background-color:#ffeecc"|문제점
 +
|-
 +
|align=center| 버튼을 눌렀을때 알람이 시작되게 하려면?
 +
|'''*''' 새로운 기능으로 변경하려고 기존코드의 내용을 수정해야 하므로 OCP에 위배된다. <br> '''*''' Button 클래스의 pressed() 전체를 변경해야한다.
 +
|}
 +
 
 +
  public class Alarm {
 +
    public void start(){ System.out.println("Alarming"); }
 +
  }
 +
  public class Button {
 +
    private Alarm theAlarm;
 +
    public Button(Alarm theAlarm) { this.theAlarm = theAlarm; }
 +
    public void pressed() { theAlarm.start(); }
 +
  } <br>
 +
  public class Client {
 +
  public static void main(String[] args) {
 +
    Alarm alarm = new Alarm();
 +
    Button alarmButton = new Button(alarm);
 +
    alarmButton.pressed();
 +
    }
 +
  }
 +
 
 +
* 버튼을 누르는 동작에 따라 다른 기능을 실행하는 경우<ref name="커맨드패턴예시" />
 +
 
 +
:{|class=wikitable width=850 style="background-color:#ffffee"
 +
|-
 +
!align=center style="background-color:#ffeecc"|궁금점
 +
!align=center style="background-color:#ffeecc"|문제점
 +
|-
 +
|align=center| 버튼을 처음 눌렀을 때는 램프를 켜고, 두 번째 눌렀을 때는 알람을 동작하게 하려면?
 +
|'''*''' 필요한 기능을 새로 추가할 때마다 Button 클래스의 코드를 수정해야 하므로 재사용하기 어렵다.
 +
|}
 +
 
 +
  enum Mode { LAMP, ALARM };  // Button 클래스의 코드를 수정
 +
  public class Button {
 +
    private Lamp theLamp;
 +
    private Alarm theAlarm;
 +
    private Mode theMode; 
 +
    // 생성자에서 버튼을 눌렀을 때 필요한 기능을 인지로 받는다.
 +
    public Button(Lamp theLamp, Alarm theAlarm) {
 +
    this.theLamp = theLamp;
 +
    this.theAlarm = theAlarm;
 +
  }
 +
  // 램프 모드 또는 알람 모드를 설정
 +
  public void setMode(Mode mode) { this.theMode = mode; }
 +
  // 설정된 모드에 따라 램프를 켜거나 알람을 울림
 +
  public void pressed() {
 +
  switch(theMode) {
 +
  case LAMP: theLamp.turnOn(); break;
 +
  case ALARM: theAlarm.start(); break;
 +
    }
 +
  }
 +
  }
 +
 
 +
=== 해결책 ===
 +
* 문제를 해결하기 위해서는 구체적인 기능을 직접 구현하는 대신 실행될 기능을 캡슐화해야 한다. <ref name="커맨드패턴예시 />
 +
 
 +
{{각주}}
 +
 
 +
 
 +
== 참고자료 ==
 +
 
 +
 
 
== 같이보기 ==
 
== 같이보기 ==
 
* [[디자인패턴]]
 
* [[디자인패턴]]
== 참고자료 ==
+
 
{{프로그래밍|토막글}}
+
 
 +
 
 +
{{프로그래밍|검토 필요}}

2020년 8월 21일 (금) 15:39 판

커맨드패턴(Command pattern)은 요청을 객체의 형태로 캡슐화하여 사용자가 보낸 요청을 나중에 이용할 수 있도록 매서드 이름, 매개변수 등 요청에 필요한 정보를 저장 또는 로깅, 취소할 수 있게 하는 패턴이다.[1]


특징

커맨드 패턴에는 명령(command), 수신자(receiver), 발동자(invoker), 클라이언트(client)의 네개의 용어가 항상 따른다. 커맨드 객체는 수신자 객체를 가지고 있으며, 수신자의 메서드를 호출하고, 이에 수신자는 자신에게 정의된 메서드를 수행한다. 커맨드 객체는 별도로 발동자 객체에 전달되어 명령을 발동하게 한다. 발동자 객체는 필요에 따라 명령 발동에 대한 기록을 남길 수 있다. 한 발동자 객체에 다수의 커맨드 객체가 전달될 수 있다. 클라이언트 객체는 발동자 객체와 하나 이상의 커맨드 객체를 보유한다. 클라이언트 객체는 어느 시점에서 어떤 명령을 수행할지를 결정한다. 명령을 수행하려면, 클라이언트 객체는 발동자 객체로 커맨드 객체를 전달한다. [1]

커맨드 패턴 클래스 다이어그램

예시

  • 만능 버튼 만들기 : 버튼이 눌리면 램프의 불이 켜지는 프로그램 [2]
 public class Lamp {
 public void turnOn(){ System.out.println("Lamp On"); }
 }
 public class Button {
 private Lamp theLamp;
 public Button(Lamp theLamp) { this.theLamp = theLamp; }  // 버튼 클래스의 생성자를 이용해 불을 켤 램프의 객체를 전달한다.
 public void pressed() { theLamp.turnOn(); }
 } 
public class Client { public static void main(String[] args) { Lamp lamp = new Lamp(); Button lampButton = new Button(lamp); // 버튼 클래스의 pressed가 호출되면 생성자를 통해 전달받은 램프 객체의 turnOn()을 호출해 불을 켠다. lampButton.pressed(); } }

문제점

  • 버튼을 눌렀을 때 다른 기능을 실행하는 경우[2]
궁금점 문제점
버튼을 눌렀을때 알람이 시작되게 하려면? * 새로운 기능으로 변경하려고 기존코드의 내용을 수정해야 하므로 OCP에 위배된다.
* Button 클래스의 pressed() 전체를 변경해야한다.
 public class Alarm {
   public void start(){ System.out.println("Alarming"); }
 }
 public class Button {
   private Alarm theAlarm;
   public Button(Alarm theAlarm) { this.theAlarm = theAlarm; }
   public void pressed() { theAlarm.start(); }
 } 
public class Client { public static void main(String[] args) { Alarm alarm = new Alarm(); Button alarmButton = new Button(alarm); alarmButton.pressed(); } }
  • 버튼을 누르는 동작에 따라 다른 기능을 실행하는 경우[2]
궁금점 문제점
버튼을 처음 눌렀을 때는 램프를 켜고, 두 번째 눌렀을 때는 알람을 동작하게 하려면? * 필요한 기능을 새로 추가할 때마다 Button 클래스의 코드를 수정해야 하므로 재사용하기 어렵다.
 enum Mode { LAMP, ALARM };  // Button 클래스의 코드를 수정
 public class Button {
   private Lamp theLamp;
   private Alarm theAlarm;
   private Mode theMode;  
   // 생성자에서 버튼을 눌렀을 때 필요한 기능을 인지로 받는다.
   public Button(Lamp theLamp, Alarm theAlarm) {
    this.theLamp = theLamp;
    this.theAlarm = theAlarm;
 }
 // 램프 모드 또는 알람 모드를 설정
 public void setMode(Mode mode) { this.theMode = mode; }
 // 설정된 모드에 따라 램프를 켜거나 알람을 울림
 public void pressed() {
  switch(theMode) {
  case LAMP: theLamp.turnOn(); break;
  case ALARM: theAlarm.start(); break;
    }
  }
 }

해결책

  • 문제를 해결하기 위해서는 구체적인 기능을 직접 구현하는 대신 실행될 기능을 캡슐화해야 한다. [2]

각주

  1. 1.0 1.1 커맨드 패턴〉, 《위키백과》
  2. 2.0 2.1 2.2 2.3 커맨드 패턴예시〉, 《Design Pattern》


참고자료

같이보기



  검수요청.png검수요청.png 이 커맨드패턴 문서는 프로그래밍에 관한 글로서 검토가 필요합니다. 위키 문서는 누구든지 자유롭게 편집할 수 있습니다. [편집]을 눌러 문서 내용을 검토·수정해 주세요.