라고도 함: Strategy
Strategy Pattern은 일련의 알고리즘을 정의하고 각 알고리즘을 별도의 클래스에 넣을 수 있는 동작 디자인 패턴입니다. 알고리즘을 서로 교체할 수 있습니다.
언젠가는 관광객을 위한 여행 가이드 앱을 만들 계획입니다. 프로그램의 핵심 기능은 사용자가 어떤 도시에서든 빠르게 방향을 잡을 수 있도록 아름다운 지도를 제공하는 것입니다.
사용자가 기대하는 앱의 새로운 기능은 자동 경로 계획입니다. 사용자는 주소를 입력하고 지도에서 목적지까지 가장 빠른 경로를 보고 싶어합니다.
프로그램의 첫 번째 버전에서는 도로 경로만 계획할 수 있습니다. 자동차로 여행하는 사람들은 매우 만족합니다. 그러나 분명히 모든 사람이 휴가 중에 운전하는 것은 아닙니다. 그래서 다음 업데이트에는 도보 경로를 계획하는 기능을 추가했습니다. 이후 대중교통 경로를 계획하는 기능이 추가되었습니다.
그리고 이것은 시작에 불과합니다. 곧 자전거 이용자를 위한 경로를 계획하게 됩니다. 잠시 후, 도시의 모든 명소를 방문하기 위한 경로를 다시 계획해야 합니다.
가이드 코드가 매우 부풀어오르게 됩니다.
이 애플리케이션은 비즈니스 관점에서는 매우 성공적이지만 기술적인 부분은 큰 골칫거리입니다. 새로운 경로 계획 알고리즘이 추가될 때마다 투어 가이드 애플리케이션의 기본 클래스 크기가 두 배로 늘어납니다. 마침내 어떤 시점에서는 이 코드 더미를 더 이상 유지할 수 없다고 느끼게 됩니다.
간단한 결함을 수정하든, 거리 가중치를 미세 조정하든, 알고리즘을 수정하면 전체 클래스에 영향을 미치므로 이미 작동하는 코드에 버그가 발생할 위험이 높아집니다.
또한 팀워크가 비효율적이게 됩니다. 앱이 성공적으로 출시된 후 팀원을 모집하면 병합 충돌 작업에 너무 많은 시간이 소요된다고 불평할 것입니다. 새로운 기능을 구현하는 과정에서 팀은 동일한 거대한 클래스를 수정해야 하므로 작성하는 코드가 서로 충돌할 수 있습니다.
전략 패턴은 다양한 방식으로 특정 작업을 수행하는 클래스를 식별한 다음 그 안에 있는 알고리즘을 전략이라는 독립적인 클래스 집합으로 추출하는 것을 제안합니다.
context라는 원래 클래스에는 각 전략에 대한 참조를 저장하기 위한 멤버 변수가 포함되어야 합니다. 컨텍스트는 작업을 수행하지 않지만 연결된 정책 개체에 작업을 위임합니다.
컨텍스트는 작업 요구 사항을 충족하는 알고리즘을 선택하는 일을 담당하지 않습니다. 클라이언트는 필요한 전략을 컨텍스트에 전달합니다. 실제로 컨텍스트는 전략에 대해 많이 알지 못하며 동일한 공통 인터페이스를 통해 모든 전략과 상호 작용하며 선택한 전략에 캡슐화된 알고리즘을 트리거하는 메서드만 노출하면 됩니다.
따라서 상황은 특정 전략과 무관할 수 있습니다. 이를 통해 컨텍스트 코드나 기타 전략을 변경하지 않고도 새 알고리즘을 추가하거나 기존 알고리즘을 수정할 수 있습니다.
경로 계획 전략.
여행 가이드 애플리케이션에서는 단 하나의 buildRoute
경로 생성 방법을 사용하여 각 경로 계획 알고리즘을 독립적인 클래스로 추출할 수 있습니다. 이 메서드는 시작점과 끝점을 매개변수로 받고 경로 중간점 모음을 반환합니다.
각 경로 계획 클래스에 전달된 매개변수가 정확히 동일하더라도 생성되는 경로는 완전히 다를 수 있습니다. 기본 투어 가이드 클래스의 주요 작업은 지도에 일련의 중간 지점을 렌더링하는 것이며 알고리즘이 선택되는 방식에는 관심이 없습니다. 이 클래스에는 현재 경로 계획 전략을 전환하는 메서드도 있으므로 클라이언트(예: 사용자 인터페이스의 버튼)는 현재 선택된 경로 계획 동작을 다른 전략으로 바꿀 수 있습니다.
공항까지의 다양한 여행 전략
공항에 가야 한다면. 버스를 타거나, 택시를 예약하거나, 자전거를 탈 수 있습니다. 이것이 당신의 여행 전략입니다. 예산이나 시간과 같은 요소를 기반으로 이러한 전략 중 하나를 선택할 수 있습니다.
Context(컨텍스트)는 특정 전략에 대한 참조를 유지하고 전략 인터페이스를 통해서만 이 개체와 통신합니다.
Strategy(Strategy) 인터페이스는 모든 특정 전략에 대한 공통 인터페이스이며 전략을 실행하기 위한 컨텍스트 메서드를 선언합니다.
Concrete Strategies는 컨텍스트에서 사용되는 알고리즘의 다양한 변형을 구현합니다.
컨텍스트가 알고리즘을 실행해야 할 때 연결된 전략 개체에 대해 실행 메서드를 호출합니다. 관련된 전략의 유형과 알고리즘이 실행되는 방식에 대한 맥락이 불분명합니다.
Client(클라이언트)는 특정 전략 개체를 생성하여 컨텍스트에 전달합니다. 컨텍스트는 클라이언트가 런타임 시 관련 정책을 재정의할 수 있도록 setter를 제공합니다.
이 예에서 컨텍스트는 여러 전략을 사용하여 다양한 계산 작업을 수행합니다.
// 策略接口声明了某个算法各个不同版本间所共有的操作。上下文会使用该接口来 // 调用有具体策略定义的算法。 interface Strategy is method execute(a, b) // 具体策略会在遵循策略基础接口的情况下实现算法。该接口实现了它们在上下文 // 中的互换性。 class ConcreteStrategyAdd implements Strategy is method execute(a, b) is return a + b class ConcreteStrategySubtract implements Strategy is method execute(a, b) is return a - b class ConcreteStrategyMultiply implements Strategy is method execute(a, b) is return a * b // 上下文定义了客户端关注的接口。 class Context is // 上下文会维护指向某个策略对象的引用。上下文不知晓策略的具体类。上下 // 文必须通过策略接口来与所有策略进行交互。 private strategy: Strategy // 上下文通常会通过构造函数来接收策略对象,同时还提供设置器以便在运行 // 时切换策略。 method setStrategy(Strategy strategy) is this.strategy = strategy // 上下文会将一些工作委派给策略对象,而不是自行实现不同版本的算法。 method executeStrategy(int a, int b) is return strategy.execute(a, b) // 客户端代码会选择具体策略并将其传递给上下文。客户端必须知晓策略之间的差 // 异,才能做出正确的选择。 class ExampleApplication is method main() is 创建上下文对象。 读取第一个数。 读取最后一个数。 从用户输入中读取期望进行的行为。 if (action == addition) then context.setStrategy(new ConcreteStrategyAdd()) if (action == subtraction) then context.setStrategy(new ConcreteStrategySubtract()) if (action == multiplication) then context.setStrategy(new ConcreteStrategyMultiply()) result = context.executeStrategy(First number, Second number) 打印结果。
객체에서 다양한 알고리즘 변형을 사용하고 런타임 시 알고리즘을 전환할 수 있기를 원하는 경우 전략 모드를 사용할 수 있습니다.
전략 패턴을 사용하면 객체를 다양한 방식으로 특정 하위 작업을 수행할 수 있는 다양한 하위 객체에 연결하여 런타임 시 객체 동작을 간접적으로 변경할 수 있습니다.
특정 동작을 수행하는 데 약간만 다른 유사한 클래스가 많을 때 전략 패턴을 사용하세요.
전략 패턴을 사용하면 다양한 동작을 별도의 클래스 계층 구조로 추출하고 원래 클래스를 동일한 클래스로 결합하여 코드 중복을 줄일 수 있습니다.
알고리즘이 컨텍스트 논리에서 특별히 중요하지 않은 경우 이 패턴을 사용하면 알고리즘 구현 세부 사항에서 클래스의 비즈니스 논리를 분리할 수 있습니다.
전략 패턴을 사용하면 코드, 내부 데이터 및 다양한 알고리즘의 종속성을 다른 코드에서 격리할 수 있습니다. 다양한 클라이언트는 간단한 인터페이스를 통해 알고리즘을 실행할 수 있으며 런타임 시 전환될 수 있습니다.
이 패턴은 클래스에서 복잡한 조건부 연산자를 사용하여 동일한 알고리즘의 다양한 변형 간에 전환할 때 사용할 수 있습니다.
전략 패턴은 동일한 인터페이스에서 상속된 모든 알고리즘을 독립적인 클래스로 추출하므로 조건문이 더 이상 필요하지 않습니다. 기본 객체는 알고리즘의 모든 변형을 구현하지 않지만 대신 개별 알고리즘 객체 중 하나에 실행을 위임합니다.
컨텍스트 클래스에서 가장 자주 수정되는 알고리즘을 찾아보세요(런타임에 특정 알고리즘 변형을 선택하는 데 사용되는 복잡한 조건부 연산자일 수도 있음).
이 알고리즘의 모든 변형에 대한 공통 전략 인터페이스를 선언합니다.
알고리즘을 해당 클래스로 하나씩 추출하고 모두 전략 인터페이스를 구현해야 합니다.
전략 개체에 대한 참조를 저장하려면 컨텍스트 클래스에 멤버 변수를 추가하세요. 그런 다음 멤버 변수를 수정하는 setter를 제공합니다. 컨텍스트는 정책 인터페이스를 통해서만 정책 개체와 상호 작용할 수 있습니다. 필요한 경우 정책이 해당 데이터에 액세스할 수 있도록 인터페이스를 정의할 수 있습니다.
클라이언트는 컨텍스트가 예상되는 방식으로 주요 작업을 완료할 수 있도록 컨텍스트 클래스를 해당 정책과 연결해야 합니다.
런타임에 개체 내에서 알고리즘을 전환할 수 있습니다.
알고리즘을 사용하는 코드에서 알고리즘 구현을 분리할 수 있습니다.
상속 대신 구성을 사용할 수 있습니다.
개폐 원칙. 상황을 수정하지 않고도 새로운 전략을 도입할 수 있습니다.
알고리즘이 거의 변경되지 않는다면 새로운 클래스와 인터페이스를 도입할 이유가 없습니다. 이 패턴을 사용하면 프로그램이 지나치게 복잡해집니다.
클라이언트는 전략 간의 차이점을 알아야 합니다. 적절한 전략을 선택해야 합니다.
많은 최신 프로그래밍 언어는 함수 유형 기능을 지원하므로 일련의 익명 함수에서 다양한 버전의 알고리즘을 구현할 수 있습니다. 이렇게 하면 코드를 단순하게 유지하기 위해 추가 클래스와 인터페이스를 사용할 필요 없이 정책 개체를 사용하는 것과 정확히 동일한 방식으로 이러한 기능을 사용할 수 있습니다.
Bridge, Stateful 및 Strategy(어느 정도는 Adapter) 패턴의 인터페이스는 매우 유사합니다. 실제로 이들은 모두 구성 패턴을 기반으로 합니다. 즉, 작업을 다른 개체에 위임하지만 각각 다른 문제를 해결합니다. 패턴은 특정 방식으로 코드를 구성하는 방법일 뿐만 아니라 패턴을 사용하여 다른 개발자와 해결하는 문제를 논의할 수도 있습니다.
명령 패턴과 전략은 둘 다 특정 동작으로 객체를 매개변수화할 수 있기 때문에 비슷해 보입니다. 그러나 그들의 의도는 매우 다릅니다.
명령을 사용하여 모든 작업을 개체로 변환할 수 있습니다. 작업의 매개변수는 개체의 멤버 변수가 됩니다. 변환을 사용하여 작업 실행을 지연하거나, 작업을 대기열에 추가하거나, 기록 명령을 저장하거나, 원격 서비스에 명령을 보낼 수 있습니다.
반면에 전략은 무언가를 달성하는 다양한 방법을 설명하는 데 종종 사용되어 동일한 컨텍스트 클래스 내에서 알고리즘을 전환할 수 있습니다.
장식 모드를 사용하면 물체의 모양을 바꿀 수 있고, 전략을 사용하면 물체의 본질을 바꿀 수 있습니다.
템플릿 메서드 패턴은 상속 메커니즘을 기반으로 합니다. 즉, 하위 클래스의 콘텐츠 일부를 확장하여 알고리즘의 일부를 변경할 수 있습니다. 전략은 구성 메커니즘을 기반으로 합니다. 즉, 해당 동작에 대해 다양한 전략을 제공하여 개체 동작의 일부를 변경할 수 있습니다. 템플릿 메소드는 클래스 수준에서 작동하므로 정적입니다. 정책은 개체 수준에서 작동하므로 런타임에 동작을 전환할 수 있습니다.
상태는 전략의 확장으로 생각할 수 있습니다. 둘 다 구성 메커니즘을 기반으로 합니다. 둘 다 작업의 일부를 "도우미" 개체에 위임하여 다양한 상황에서 동작을 변경합니다. 정책은 이러한 개체를 서로 완전히 독립적으로 만들고 다른 개체의 존재를 인식하지 못하게 합니다. 그러나 상태 패턴은 특정 상태 간의 종속성을 제한하지 않으며 다양한 시나리오에서 상태를 변경할 수 있도록 허용합니다.
위 내용은 자바 디자인 패턴의 전략 패턴은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!