답변:
솔직히, 두 패턴은 실제로 매우 유사하며, 이들 사이의 정의 차이는 요청한 사람에 따라 달라지는 경향이 있습니다. 몇 가지 인기있는 선택은 다음과 같습니다.
"클래식"구현은 목록의 모든 항목에 대해 State 또는 Strategy와 일치하지만 둘을 혼합 한 하이브리드에서 실행됩니다. 특정 국가가 더 많은 국가 나 전략에 속하는지 여부는 궁극적으로 주관적인 질문입니다.
getStatus()
객체의 상태에 따라 다른 상태를 반환 하는
메소드가있을 수 있지만 메소드의 호출자는 각 잠재적 상태를 설명하기 위해 다르게 코딩 될 필요는 없습니다.차이점은 단순히 다른 문제를 해결한다는 것입니다.
그러나 서로 다른 목표를 달성하기위한 구성은 매우 유사합니다. 두 패턴 모두 위임이있는 구성의 예입니다.
그들의 장점에 대한 관찰 :
사용하여 주 패턴을 국가 지주 (컨텍스트) 클래스의 지식 안도 어떤 상태 또는이고 무엇이 상태 또는 사용할 수있는 유형을 입력합니다. 이는 클래스가 OCP (Open-Closed Design Principal)를 준수 함을 의미합니다. 클래스는 상태 / 유형의 변화에 따라 닫히지 만 상태 / 유형은 확장 가능합니다.
전략 패턴 을 사용하면 알고리즘 사용 (컨텍스트) 클래스가 특정 작업 ( "알고리즘")을 수행하는 방법 에 대한 지식이 없어집니다 . 이 경우에도 OCP를 준수합니다. 이 작업을 수행하는 방법에 대한 변경 사항은 클래스가 닫히지 만 디자인은이 작업을 해결하기 위해 다른 알고리즘을 추가 할 수 있습니다.
이는 컨텍스트 클래스의 단일 책임 원칙 (SRP) 준수를 향상시킬 수도 있습니다. 또한 알고리즘은 다른 클래스에서 쉽게 재사용 할 수있게됩니다.
누군가 평신도의 용어로 설명해 주시겠습니까?
디자인 패턴은 실제로 "레이맨"개념은 아니지만 가능한 한 명확하게하기 위해 노력할 것입니다. 모든 디자인 패턴은 3 차원으로 고려 될 수 있습니다.
상태와 전략을 비교해 봅시다.
상태 는 두 경우 중 하나에 사용됩니다 [GoF book p. 306] :
- 객체의 동작은 상태에 따라 다르며 해당 상태에 따라 런타임에 동작을 변경해야합니다.
- 작업에는 개체의 상태에 따라 큰 여러 부분으로 된 조건문이 있습니다. 이 상태는 일반적으로 하나 이상의 열거 된 상수로 표시됩니다. 종종 여러 작업에 동일한 조건부 구조가 포함됩니다. State 패턴은 조건부의 각 분기를 별도의 클래스에 넣습니다. 이를 통해 객체 상태를 다른 객체와 독립적으로 변할 수있는 자체 객체로 취급 할 수 있습니다.
상태 패턴으로 해결되는 문제가 실제로 있는지 확인하려면 유한 상태 기계를 사용하여 객체의 상태를 모델링 할 수 있어야 합니다 . 여기 에서 적용된 예제를 찾을 수 있습니다 .
각 상태 전이는 상태 인터페이스의 방법입니다. 이는 디자인의 경우이 패턴을 적용하기 전에 상태 전이에 대해 확실해야 함을 의미합니다. 그렇지 않으면 전환을 추가하거나 제거하는 경우 인터페이스와 해당 전환을 구현하는 모든 클래스를 변경해야합니다.
나는 개인적 으로이 패턴을 유용하게 찾지 못했습니다. 룩업 테이블을 사용하여 유한 상태 머신을 항상 구현할 수 있습니다 (OO 방식은 아니지만 꽤 잘 작동합니다).
전략 은 다음 [GoF book p. 316] :
- 많은 관련 클래스는 동작이 다릅니다. 전략은 여러 가지 동작 중 하나를 사용하여 클래스를 구성하는 방법을 제공합니다.
- 알고리즘의 다른 변형이 필요합니다. 예를 들어, 다른 시공간 상충 관계를 반영하는 알고리즘을 정의 할 수 있습니다. 이러한 변형이 알고리즘의 클래스 계층으로 구현 될 때 전략을 사용할 수 있습니다 [HO87].
- 알고리즘은 클라이언트가 알아야 할 데이터를 사용합니다. 복잡한 알고리즘 별 데이터 구조가 노출되지 않도록 전략 패턴을 사용하십시오.
- 클래스는 많은 동작을 정의하며 동작에서 여러 조건문으로 나타납니다. 많은 조건부 대신 관련 조건부 분기를 자체 전략 클래스로 이동하십시오.
전략을 적용 할 마지막 경우는 조건부를 다형성 으로 바꾸기로 알려진 리팩토링과 관련이 있습니다.
요약 : 상태 및 전략은 매우 다른 문제를 해결합니다. 유한 상태 머신으로 문제를 모델링 할 수없는 경우 상태 패턴이 적절하지 않을 수 있습니다. 복잡한 알고리즘의 변형을 캡슐화하는 데 문제가 없다면 전략은 적용되지 않습니다.
State 는 다음 UML 클래스 구조를 갖습니다.
전략 은 다음 UML 클래스 구조를 갖습니다.
요약 : 정적 구조와 관련하여이 두 패턴은 대부분 동일합니다. 사실, 다음과 같은 패턴을 검출 툴 이 하나는 그 "고려 에서 [...] 동일한 패턴이다 (개념적 정보를 참조하지 않고, 예), 자동 공정에 의해 그 차이를 금지. 구조 "를
그러나 ConcreteStates가 자체적으로 상태 전이를 결정하는 경우 큰 차이가있을 수 있습니다 ( 위의 다이어그램에서 "" 결정할 수있는 "연관 "참조 ). 이로 인해 콘크리트 상태가 서로 연결됩니다. 예를 들어 (다음 섹션 참조) 상태 A는 상태 B 로의 전환을 결정합니다. 컨텍스트 클래스가 다음 구체적 상태로의 전환을 결정하면 이러한 종속성이 사라집니다.
위의 문제 섹션에서 언급 한 바와 같이, 국가는 일부에 따라 실행 시간에 그 동작 변경을 의미 상태 객체의를. 그러므로, 유한 상태 머신 의 관계에서 논의 된 바와 같이, 상태 천이 의 개념이 적용된다 . [GoF]는 전환이 ConcreteState 서브 클래스 또는 중앙 위치 (예 : 테이블 기반 위치)에서 정의 될 수 있다고 언급합니다.
간단한 유한 상태 머신을 가정 해 봅시다 :
서브 클래스가 다음 상태 객체를 반환하여 상태 전이를 결정한다고 가정하면 동적은 다음과 같습니다.
전략 의 역학을 보여주기 위해 실제 예제 를 빌리는 것이 유용합니다 .
요약 : 각 패턴은 상황에 따라 무언가를하기 위해 다형성 호출을 사용합니다. 상태 패턴에서 다형성 호출 (전환)은 종종 다음 상태를 변경합니다 . 전략 패턴에서 다형성 통화는 일반적으로 컨텍스트를 변경하지 않습니다 (예 : 신용 카드로 한 번 지불한다고해서 다음에 PayPal로 지불한다는 의미는 아닙니다). 다시, 상태 패턴의 동역학은 해당 패턴 상태 기계에 의해 결정되는데 , 이는이 패턴의 올바른 적용에 필수적입니다.
전략 패턴에는 호스팅 클래스에서 알고리즘 구현을 이동하여 별도의 클래스에 배치하는 것이 포함됩니다. 이것은 호스트 클래스가 각 알고리즘 자체의 구현을 제공 할 필요가 없다는 것을 의미하며, 이는 부정한 코드로 이어질 수 있습니다.
정렬 알고리즘은 일반적으로 모두 같은 종류 (정렬)를 수행하므로 예제로 사용됩니다. 각각의 다른 정렬 알고리즘이 자체 클래스에 배치되면 클라이언트는 사용할 알고리즘을 쉽게 선택할 수 있으며 패턴은 액세스하기 쉬운 방법을 제공합니다.
상태 패턴은 객체의 상태가 변경 될 때 객체의 동작을 변경하는 것을 포함합니다. 이것은 호스트 클래스가 모든 다른 상태에 대해 동작 구현을 제공하지 않음을 의미합니다. 호스트 클래스는 일반적으로 주어진 상태에서 필요한 기능을 제공하는 클래스를 캡슐화하고 다른 클래스로 전환합니다. 상태가 바뀔 때
고객 통화를 처리하는 IVR (Interactive Voice Response) 시스템을 고려하십시오. 고객이 다음을 처리하도록 프로그래밍 할 수 있습니다.
이 상황을 처리하기 위해 상태 패턴을 사용할 수 있습니다 .
고객을 지원 임원과 연결하는이 프로세스 는 다음 중 하나를 기반으로 임원을 선택 하는 전략 패턴을 사용하여 구현할 수 있습니다 .
전략 패턴 '을 결정 하는 방법을 몇 가지 작업을 수행 할'와 국가 패턴 '을 결정 하면 이를 수행 할'.
전략 : 전략은 고정되어 있으며 일반적으로 여러 단계로 구성됩니다. (정렬은 한 단계 만 구성하므로이 패턴의 목적을 이해하기에는 너무 원시적이므로 매우 나쁜 예입니다). 전략의 "주요"루틴은 몇 가지 추상 메소드를 호출하는 것입니다. 예를 들어 "Enter Room Strategy", "main-method"는 goThroughDoor ()입니다. approachDoor (), if (locked ()) openLock (); openDoor (); enterRoom (); 회전(); 문을 닫다(); if (wasLocked ()) lockDoor ();
이제 잠긴 문을 통해 한 방에서 다른 방으로 이동하기위한이 일반적인 "알고리즘"의 하위 클래스는 알고리즘 단계를 구현할 수 있습니다.
다시 말해, 전략을 서브 클래 싱하는 것은 기본 알고리즘을 변경하지 않으며 개별 단계 만 변경합니다.
위의 내용은 템플릿 방법 패턴입니다. 이제 함께 속한 단계 (잠금 해제 / 잠금 및 열기 / 닫기)를 자체 구현 객체에 넣고 위임합니다. 예를 들어 열쇠가 달린 자물쇠와 코드 카드가 달린 자물쇠는 두 종류의 자물쇠입니다. 전략에서 "단계"오브젝트로 위임하십시오. 이제 전략 패턴이 있습니다.
상태 패턴은 완전히 다릅니다.
랩핑 오브젝트와 랩핑 된 오브젝트가 있습니다. 랩핑 된 것은 "상태"입니다. 상태 객체는 래퍼를 통해서만 액세스됩니다. 이제 래핑 된 객체를 언제든지 변경할 수 있으므로 래퍼의 상태 또는 "클래스"또는 유형이 변경되는 것 같습니다.
예를 들어 로그온 서비스가 있습니다. 사용자 이름과 비밀번호를 허용합니다. 하나의 메소드 만 있습니다 : logon (String userName, String passwdHash). 로그온의 승인 여부를 스스로 결정하는 대신 결정을 상태 개체에 위임합니다. 이 상태 개체는 일반적으로 사용자 / 패스 조합이 유효한지 확인하고 로그온을 수행합니다. 그러나 이제 "Checker"를 권한있는 사용자 만 로그온 할 수있는 방법 (예 : 메인 타 나스 시간 동안) 또는 아무도 로그온 할 수없는 방법으로 교환 할 수 있습니다. "체커"는 시스템의 "로그온 상태"를 나타냅니다.
가장 중요한 차이점은 전략을 선택했을 때 끝날 때까지 전략을 고수하는 것입니다. 즉, "메인 메소드"를 호출하고 실행중인 한 전략을 변경하지 않습니다. 시스템 실행 중 상태 패턴 상황에서 OTOH는 적절하다고 판단되면 상태를 임의로 변경합니다.
전략 패턴은 특정 작업에 대해 여러 알고리즘이 있고 클라이언트가 런타임에 사용될 실제 구현을 결정하는 경우에 사용됩니다.
Wiki 전략 패턴 기사의 UML 다이어그램 :
주요 특징들:
자세한 정보 및 실제 예는이 게시물을 참조하십시오.
상태 패턴을 사용하면 내부 상태가 변경 될 때 객체의 동작을 변경할 수 있습니다
위키 상태 패턴 기사의 UML 다이어그램 :
상태에 따라 객체의 동작을 변경해야하는 경우 객체에 상태 변수가 있고 if-else 조건 블록을 사용하여 상태에 따라 다른 동작을 수행 할 수 있습니다. 상태 패턴은 컨텍스트 및 상태 구현을 통해이를 달성하기위한 체계적이고 손실 결합 방식을 제공하는 데 사용됩니다 .
자세한 내용은이 journaldev 기사를 참조하십시오.
소스 메이킹 및 journaldev 기사 와의 주요 차이점 :
평신도의 언어로
전략 패턴에서 상태가 없거나 모두 동일한 상태를 갖습니다. 다른 의사가 같은 상태의 동일한 환자의 동일한 질병을 다른 방식으로 치료하는 것과 같이 하나의 작업을 수행하는 다른 방법이 있습니다.
상태 패턴에는 주관적으로 환자의 현재 상태 (고온 또는 저온)와 같은 다음 조치 과정 (의약품 처방)이 결정될 상태에 따라 상태가 있으며 한 상태는 다른 상태로 이어질 수 있으므로 상태가 있습니다. 의존성을 기술하기 위해 (기술적으로 구성).
우리가 기술적으로 그것을 이해하려고 시도한다면, 둘의 코드 비교에 기초하여, 우리는 상황이 매우 비슷해 보이기 때문에 상황의 주관성을 잃을 수도 있습니다.
두 패턴 모두 파생 된 여러 클래스가있는 기본 클래스에 위임되지만 이러한 파생 클래스는 컨텍스트 클래스에 대한 참조를 다시 보유하는 상태 패턴에만 있습니다.
또 다른 방법은 전략 패턴이 더 간단한 버전의 상태 패턴이라는 것입니다. 원하는 경우 하위 패턴. 파생 된 상태가 컨텍스트에 대한 참조를 다시 보유하도록 하려는지 여부에 따라 다릅니다 (즉, 컨텍스트에서 메소드를 호출하도록하려는 경우).
자세한 정보 : Robert C Martin (& Micah Martin)은 "Agile Principles, Patterns and Practices in C #"라는 책에서 이에 대해 답변합니다. ( http://www.amazon.com/Agile-Principles-Patterns-Practices-C/dp/0131857258 )
이것은 꽤 오래된 질문이지만 여전히 동일한 대답을 찾고 있었고 이것이 내가 발견 한 것입니다.
State 패턴의 경우 Medial Player Play 버튼의 예를 고려하십시오. 재생하면 재생이 시작되고 컨텍스트가 재생 중임을 인식합니다. 클라이언트가 재생 작업을 수행하려고 할 때마다 플레이어의 현재 상태를 확인합니다. 이제 클라이언트는 컨텍스트 객체를 통해 객체의 상태가 재생되고 있음을 알기 때문에 일시 중지 상태 객체 작업 메서드를 호출합니다. 클라이언트가 상태를 실현하고 조치를 수행해야하는 상태를 자동화 할 수 있습니다.
https://www.youtube.com/watch?v=e45RMc76884 https://www.tutorialspoint.com/design_pattern/state_pattern.htm
전략 패턴의 경우 클래스 다이어그램의 배열은 상태 패턴과 동일합니다. 클라이언트는이 작업을 수행하기 위해이 작업을 수행합니다. 즉, 다른 상태 대신 다른 알고리즘, 예를 들어 패턴에 대해 수행해야하는 다른 분석이 있습니다. 여기서 클라이언트는 어떤 알고리즘 (비즈니스 정의 사용자 정의 알고리즘)을 원하는지 컨텍스트에 알려주고이를 수행합니다.
https://www.tutorialspoint.com/design_pattern/strategy_pattern.htm
두 가지 모두 개방형 원칙을 구현하므로 개발자는 상태 패턴에 새로운 상태를 추가하고 새로운 알고리즘을 추가 할 수 있습니다.
그러나 차이점은 객체의 상태에 따라 다른 논리를 실행하는 데 사용되는 상태 패턴입니다. 전략의 경우 다른 논리입니다.
차이점은 http://c2.com/cgi/wiki?StrategyPattern 에서 설명합니다 . 합니다. 데이터 분석을 위해 전체 프레임 워크 내에서 다양한 알고리즘을 선택할 수 있도록 전략 패턴을 사용했습니다. 이를 통해 전체 프레임 워크와 로직을 변경하지 않고도 알고리즘을 추가 할 수 있습니다.
일반적인 예는 amy가 함수 최적화를위한 프레임 워크를 가지고 있다는 것입니다. 프레임 워크는 데이터 및 매개 변수를 설정합니다. 전략 패턴을 사용하면 프레임 워크를 변경하지 않고도 sttepest descents, 켤레 그라디언트, BFGS 등과 같은 알고리즘을 선택할 수 있습니다.
두 가지 작업으로 나눌 수있는 프로젝트가있는 경우 :
작업 1 : 두 가지 알고리즘 중 하나를 사용하여 수행 할 수 있습니다. alg1, alg2
작업 2 : 세 가지 알고리즘 중 하나를 사용하여 수행 할 수 있습니다. alg3, alg4, alg5
alg1과 alg2는 서로 호환 가능합니다. alg3, alg4 및 alg5는 서로 호환됩니다.
작업 1과 작업 2에서 수행 할 알고리즘 선택은 상태에 따라 다릅니다.
상태 1 : 작업 1에 alg1이 필요하고 작업 2에 alg3이 필요합니다.
상태 2 : 작업 1에 alg2가 필요하고 작업 2에 alg5가 필요합니다.
컨텍스트는 상태 객체를 상태 1에서 상태 2로 변경할 수 있습니다. 그러면 alg1 및 alg3 대신 alg2 및 alg5가 작업을 수행합니다.
작업 1 또는 작업 2에 대해 더 많은 교환 가능한 알고리즘을 추가 할 수 있습니다. 이것은 전략 패턴입니다.
작업 1과 작업 2에서 서로 다른 알고리즘 조합으로 더 많은 상태를 가질 수 있습니다. 상태 패턴을 사용하면 한 상태에서 다른 상태로 전환하고 다른 알고리즘 조합을 수행 할 수 있습니다.
'전략'은 필요에 따라 다른 상황에서 변경할 수있는 알고리즘 일 뿐이며 무언가를 처리합니다. 전의. 파일 압축 방법을 선택할 수 있습니다. 방법에 zip 또는 rar ...
그러나 '상태'는 모든 객체의 동작을 변경할 수 있으며, 변경 될 때 다른 필드를 변경할 수도 있습니다. 그래서 그 소유자에 대한 참조가 있습니다. 객체 필드를 변경하면 객체 동작이 전혀 변경 될 수 있습니다. 전의. obj에서 State0을 State1로 변경하면 정수를 10으로 변경합니다. 따라서 일부 계산을 수행하고 해당 정수를 사용하는 obj.f0 ()을 호출하면 결과에 영향을줍니다.