[design-patterns] 전략 패턴 및 명령 패턴 사용

두 디자인 패턴 모두 알고리즘을 캡슐화하고 호출 클래스에서 구현 세부 사항을 분리합니다. 내가 알아볼 수있는 유일한 차이점은 전략 패턴은 실행을위한 매개 변수를 사용하지만 명령 패턴은 그렇지 않다는 것입니다.

명령 패턴은 생성 될 때 사용할 수있는 모든 정보를 필요로하며 호출을 지연시킬 수 있습니다 (아마도 스크립트의 일부로).

한 패턴을 사용할 것인지 다른 패턴을 사용할 것인지 결정하는 기준은 무엇입니까?



답변

이 두 패턴의 차이점을 설명하는 데 도움이되는 여러 GoF 디자인 패턴의 캡슐화 계층 테이블을 포함합니다. 바라건대 각각이 캡슐화하는 것을 더 잘 설명하므로 내 설명이 더 의미가 있습니다.

먼저, 계층 구조는 테이블의 어느 쪽에서 시작하는지에 따라 주어진 패턴을 적용 할 수있는 범위 또는 특정 수준의 세부 정보를 캡슐화하는 데 사용할 적절한 패턴을 나열합니다.

디자인 패턴 캡슐화 계층 테이블

표에서 볼 수 있듯이 Strategy Pattern 개체는 알고리즘 구현의 세부 정보를 숨기므로 다른 전략 개체를 사용하면 동일한 기능을 수행하지만 다른 방식으로 수행됩니다. 각 전략 개체는 특정 요소에 대해 최적화되거나 다른 매개 변수에서 작동 할 수 있습니다. 공통 인터페이스를 사용하여 컨텍스트는 둘 중 하나와 안전하게 작업 할 수 있습니다.

명령 패턴은 알고리즘보다 훨씬 더 작은 수준의 세부 정보를 캡슐화합니다. 객체에 메시지를 보내는 데 필요한 세부 정보 (수신자, 선택자 및 인수)를 인코딩합니다. 프로세스 실행의 이러한 작은 부분을 객관화 할 때의 이점은 이러한 메시지를 세부 사항을 하드 코딩하지 않고도 일반적인 방식으로 다른 시점 또는 위치를 따라 호출 할 수 있다는 것입니다. 이를 통해 메시지를 한 번 이상 호출하거나 실행 전에 특정 호출의 세부 정보를 알 필요없이 시스템의 다른 부분이나 여러 시스템으로 전달할 수 있습니다.

디자인 패턴의 일반적인 경우와 같이 패턴 이름을 포함하기 위해 모든 구현이 세부적으로 동일 할 필요는 없습니다. 세부 사항은 구현 및 개체에서 인코딩되는 데이터와 메서드 인수로 인코딩되는 데이터에 따라 다를 수 있습니다.


답변

전략은 알고리즘을 캡슐화합니다. 명령은 발신자와 요청 수신자를 분리하여 요청을 객체로 변환합니다.

그것이 알고리즘이라면 어떤 일이 어떻게 될지 전략을 사용하십시오. 실행에서 메서드 호출을 분리해야하는 경우 Command를 사용합니다. 명령은 작업이나 트랜잭션과 같이 나중에 사용하기 위해 메시지를 대기열에 넣을 때 자주 사용됩니다.


답변

아주 오래된 질문에 대답합니다. (가장 많이 득표 한 대신 최신 답변을 보는 사람이 있습니까?)

유사성 때문에 갖는 것은 타당한 혼란입니다. 전략 및 명령 패턴 모두 캡슐화를 사용 합니다 . 하지만 그렇다고해서 똑같지는 않습니다.

주요 차이점 은 캡슐화 된 내용 을 이해 하는 것 입니다. 두 패턴이 모두 의존하는 OO 원칙은 다양한 것을 캡슐화하는 것 입니다.

전략의 경우에는 알고리즘이 다릅니다 . 예를 들어 하나의 전략 객체는 XML 파일로 출력하는 방법을 알고 있고 다른 하나는 JSON으로 출력하는 방법을 알고 있습니다. 다른 알고리즘은 다른 클래스에서 유지 ( 캡슐화 )됩니다. 그렇게 간단합니다.

명령의 경우 요청 자체 가 다릅니다 . 요청은 File Menu > Delete또는 Right Click > Context Menu > Delete또는 에서 올 수 있습니다 Just Delete Button pressed. 세 가지 경우 모두 동일한 유형의 명령 개체 3 개를 생성 할 수 있습니다. 이러한 명령 개체는 3 개의 삭제 요청 만 나타냅니다. 삭제 알고리즘이 아닙니다. 이제 요청은 객체의 무리이므로 쉽게 관리 할 수 ​​있습니다. 갑자기 실행 취소 또는 다시 실행과 같은 기능을 제공하는 것이 사소 해집니다.

명령이 요청 된 논리를 구현하는 방법은 중요하지 않습니다. execute ()를 호출하면 삭제를 트리거하는 알고리즘을 구현하거나 다른 객체에 위임 할 수도 있고 전략에 위임 할 수도 있습니다. 명령 패턴의 구현 세부 사항 일뿐입니다. 이것은 같이 이름이 왜 명령 이에게 정중 방법은 아니지만 요청 : -)

전략과 대조하십시오. 이 패턴은 실행되는 실제 논리 에만 관련됩니다 . 그렇게하면 최소한의 클래스 집합으로 다양한 동작 조합을 달성하여 클래스 폭발을 방지하는 데 도움이됩니다.

Command는 캡슐화에 대한 이해를 넓히는 데 도움이되며 Strategy는 캡슐화와 다형성의 자연스러운 사용을 제공합니다.


답변

제가 보는 방식은 동일한 작업을 수행하는 여러 가지 방법이 있다는 것입니다. 각각은 전략이며 런타임에 어떤 전략이 실행되는지 결정합니다.

먼저 StrategyOne을 시도해보고 결과가 충분하지 않으면 StrategyTwo를 시도해보세요 …

명령은 TryToWalkAcrossTheRoomCommand와 같이 발생해야하는 별개의 작업에 바인딩됩니다. 이 명령은 어떤 개체가 방을 가로 질러 걸어 가려고 할 때마다 실행되지만, 그 안에서 방을 가로 질러 걸어 가기 위해 StrategyOne 및 StrategyTwo를 시도 할 수 있습니다.


답변

제 생각에는 틀릴 수도 있지만 명령 을 실행 기능 또는 반응으로 취급합니다 . 최소한 두 명의 플레이어가 있어야합니다 : 액션을 요청하는 플레이어와 액션을 실행하는 플레이어. GUI는 명령 패턴의 일반적인 예입니다.

  • 응용 프로그램 도구 모음의 모든 단추는 일부 작업과 연결됩니다.
  • 이 경우 버튼이 실행자입니다.
  • 이 경우 작업은 명령입니다.

명령은 일반적으로 일부 범위 또는 비즈니스 영역에 제한되지만 필수는 아닙니다 execute(). 하나의 응용 프로그램 내 에서 청구서를 발행하거나 로켓을 시작하거나 동일한 인터페이스 (예 : 단일 메서드)를 구현하는 파일을 제거하는 명령이있을 수 있습니다 . 종종 명령은 자체 포함되어 있으므로 의도 한 작업을 처리하기 위해 실행자로부터 아무것도 필요하지 않습니다 (필요한 모든 정보는 생성시 제공됨). 때로는 명령이 상황에 따라 달라지며이 상황을 발견 할 수 있어야합니다. ( 백 스페이스 명령은 이전 문자를 올바르게 제거하기 위해 텍스트에서 캐럿 위치를 알아야합니다. 롤백 명령은 롤백 할 현재 트랜잭션을 검색해야합니다. …).

그만큼 전략은 조금 다르다 : 그것은 더 일부 지역에 바인딩됩니다. 전략은 날짜를 형식화하는 규칙 (UTC? 로케일 특정?) ( “날짜 형식 기”전략) 또는 기하학적 그림에 대한 제곱을 계산하는 규칙 ( “제곱 계산기”전략)을 정의 할 수 있습니다. 전략은 이러한 의미에서 무언가를 입력 ( “날짜”, “그림”, …)으로 받아들이고 그에 따라 결정을 내리는 플라이 웨이트 객체입니다. 아마도 전략이 아닌 최고,하지만 좋은 예와 연결된 하나 javax.xml.transform.Source의 인터페이스 : 전달 된 객체인지에 따라 DOMSource또는 SAXSource또는 StreamSource전략 (= XSLT 변환기이 경우)를 처리하는 다른 규칙을 적용합니다. 구현은 단순 switch하거나 책임 사슬 패턴을 포함 할 수 있습니다 .

그러나 실제로이 두 패턴 사이에는 공통점이 있습니다. 명령과 전략은 동일한 의미 영역 내에서 알고리즘을 캡슐화합니다.


답변

명령:

기본 구성 요소 :

  1. Command 는 다음과 같은 추상 명령에 대한 인터페이스를 선언합니다.execute()
  2. 수신자 는 특정 명령을 실행하는 방법을 알고 있습니다.
  3. Invoker 는실행 해야하는 ConcreteCommand 를 보유합니다.
  4. 클라이언트 ConcreteCommand를 생성하고 수신자를 할당합니다.
  5. ConcreteCommand Command Receiver 간의 바인딩을 정의합니다.

워크 플로우 :

클라이언트 호출 Invoker => Invoker 호출 ConcreteCommand => ConcreteCommand 는 추상 Command 를 구현하는 Receiver 메서드를 호출합니다. 메서드 .

장점 : 클라이언트는 Command 및 Receiver의 변경 사항에 영향을받지 않습니다. 호출자는 클라이언트와 수신자 간의 느슨한 결합을 제공합니다. 동일한 Invoker로 여러 명령을 실행할 수 있습니다.

명령 패턴을 사용하면동일한 Invoker 를 사용하여다른 수신기 에서 명령을 실행할 수 있습니다. 호출자가 다음 유형을 인식하지 못합니다. 수신자

개념의 이해,이 JournalDev에 한 번 봐이 기사 에 의해 판 카지 쿠마 와 dzone의 기사 에 의해 제임스 Sugrue 위키 백과 링크에 추가합니다.

명령 패턴을 사용 하여

  1. 호출자 및 명령 수신자 분리

  2. 콜백 메커니즘 구현

  3. 실행 취소 및 다시 실행 기능 구현

  4. 명령 기록 유지

java.lang.ThreadCommand 패턴 의 좋은 구현입니다 . Thread 를 호출자 및 Runnable 을 구현하는 클래스 로 ConcreteCommonad / Receiver로 , run()메소드를 Command 로 처리 할 수 ​​있습니다 .

명령 패턴의 실행 취소 / 다시 실행 버전은 Theodore Norvell의 기사 에서 읽을 수 있습니다.

전략:

전략 패턴은 이해하기 매우 간단합니다. 이 패턴을 사용하는 경우

알고리즘에 대한 여러 구현이 있으며 알고리즘 구현은 특정 조건에 따라 런타임에 변경 될 수 있습니다 .

항공사 예약 시스템의 요금 구성 요소의 예를 들어보십시오.

항공사는 성수기 및 성수기 이외의 시간대에 다른 요금을 제공하고자합니다. 여행 성수기가없는 날에는 매력적인 할인을 제공하여 수요를 자극하고자합니다.

전략 패턴 의 핵심 사항 :

  1. 행동 패턴입니다
  2. 위임을 기반으로 함
  3. 메서드 동작을 수정하여 객체의 내장을 변경합니다.
  4. 알고리즘 계열간에 전환하는 데 사용됩니다.
  5. 런타임에 개체의 동작을 변경합니다.

코드 예제가있는 관련 게시물 :

명령 디자인 패턴 사용

전략 패턴의 실제 사례


답변

저에게 차이는 의도 중 하나입니다. 두 패턴의 구현은 매우 유사하지만 용도는 다릅니다.

  • 전략 ‘의 경우, 객체를 사용하여 구성 요소가 알고있는 어떤 물체가하는 (그리고 자신의 작품의 일부를 수행하는 데 사용),하지만 상관하지 않는다 어떻게 그것을 않습니다.

  • 명령의 경우, 객체를 사용하여 구성 요소는 어느 쪽도 모른다 어떤 명령은하지 않고 어떻게 그것을 않습니다 – 그것은 단지 그것을 호출하는 방법을 알고있다. 호출자의 작업은 명령을 실행하는 것입니다. 명령에 의해 수행되는 처리는 호출자의 핵심 작업의 일부를 구성하지 않습니다.

이것이 차이점입니다. 구성 요소를 사용하는 개체가 실제로 구성 요소의 기능을 알고 있거나 관심을 갖고 있습니까? 대부분의 경우 이는 패턴 객체가 호출자에게 값을 반환하는지 여부에 따라 결정될 수 있습니다. 호출자가 패턴 객체가하는 일에 관심이 있다면 아마도 무언가를 반환하기를 원할 것이고 전략이 될 것입니다. 반환 값에 대해 신경 쓰지 않는다면 아마도 Command 일 것입니다 (참고로 Java Callable과 같은 것은 여전히 ​​Command입니다. 값을 반환하더라도 호출자는 값에 대해 신경 쓰지 않습니다. 원래 명령을 제공 한 것).