Also known as: Strategy
Strategy Pattern is a A behavioral design pattern that allows you to define a series of algorithms and put each algorithm into a separate class so that the algorithm objects can be interchanged.
One day, you plan to create a tour guide program for tourists. The core functionality of the program is to provide beautiful maps to help users quickly orient themselves in any city.
A new feature in the app that users are looking forward to is automatic route planning: They want to enter an address and see the fastest route to their destination on a map.
The first version of the program can only plan road routes. People traveling by car are very happy with it. But obviously, not everyone drives on vacation. So you added the ability to plan walking routes in your next update. You've since added the ability to plan public transportation routes.
And this is just the beginning. Soon you'll be planning routes for cyclists. After a while, you again have to plan your route to visit all the attractions in the city.
The guide code will become very bloated.
Although this application is very successful from a business point of view, its technical part can cause you a lot of headaches: every time a new route planning algorithm is added, the size of the main class in the tour guide application increases by one times. Finally at some point, you feel that you can no longer maintain this pile of code.
Whether it’s fixing a simple flaw or fine-tuning street weights, any modification to an algorithm affects the entire class, increasing the risk of introducing bugs into already functioning code.
In addition, teamwork will become inefficient. If you recruit team members after the app is successfully released, they will complain that too much time is spent working on merge conflicts. In the process of implementing new features, your team needs to modify the same huge class, so the code they write may conflict with each other.
The Strategy pattern suggests identifying the classes responsible for accomplishing a specific task in many different ways, and then extracting the algorithms within them into a set of independent classes called strategies.
The original class named context must contain a member variable to store a reference to each strategy. The context does not perform the task, but delegates the work to the connected policy object.
The context is not responsible for selecting the algorithm that meets the needs of the task - the client will pass the required strategy to the context. In fact, the context does not know much about the strategies, it interacts with all strategies through the same common interface, which only needs to expose a method to trigger the algorithm encapsulated in the selected strategy.
Thus, context can be independent of specific policies. This allows you to add new algorithms or modify existing ones without changing the context code or other strategies.
Route planning strategy.
In a tour guide application, each route planning algorithm can be extracted into an independent class with only one buildRoute
generating route method. This method receives the start and end points as parameters and returns a collection of route midpoints.
Even if the parameters passed to each route planning class are exactly the same, the routes created may be completely different. The main job of the main tour guide class is to render a series of halfway points on the map and does not care about how the algorithm is chosen. There is also a method in this class for switching the current path planning strategy, so the client (such as a button in the user interface) can replace the currently selected path planning behavior with another strategy.
Various Travel Strategies to the Airport
If you need to go to the airport. You can choose to take a bus, book a taxi or ride a bike. These are your travel strategies. You can choose one of these strategies based on factors like budget or time.
Context (Context) maintains a reference to a specific strategy and is only passed The policy interface communicates with this object.
Strategy (Strategy) interface is a common interface for all specific strategies. It declares a context method for executing the strategy.
Concrete Strategies (Concrete Strategies) implement different variations of the algorithm used by the context.
When the context needs to run an algorithm, it calls the execute method on its connected policy object. The context is unclear as to the type of strategy involved and how the algorithm is executed.
Client (Client) will create a specific policy object and pass it to the context. The context provides a setter so that the client can override the associated policy at runtime.
In this example, the context uses multiple strategies to perform different calculation operations.
// 策略接口声明了某个算法各个不同版本间所共有的操作。上下文会使用该接口来 // 调用有具体策略定义的算法。 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) 打印结果。
When you want to use various algorithm variants in the object and want to be able to switch algorithms at runtime, you can use the strategy mode.
The Strategy pattern allows you to indirectly change object behavior at runtime by associating objects to different sub-objects that can perform specific sub-tasks in different ways.
Use the Strategy pattern when you have many similar classes that differ only slightly in how they perform certain behaviors.
The Strategy pattern allows you to extract different behaviors into a separate class hierarchy and combine the original classes into the same one, thereby reducing duplicate code.
If the algorithm is not particularly important in the logic of the context, using this pattern can isolate the business logic of the class from its algorithm implementation details.
The Strategy pattern allows you to isolate the code, internal data, and dependencies of various algorithms from other code. Different clients can execute algorithms through a simple interface and can be switched at runtime.
This pattern can be used when complex conditional operators are used in the class to switch between different variants of the same algorithm.
Strategy pattern extracts all algorithms inherited from the same interface into independent classes, so conditional statements are no longer needed. The primitive object does not implement all variants of the algorithm, but instead delegates execution to one of the individual algorithm objects.
Find out the algorithm with a higher modification frequency from the context class (it may also be a complex condition used to select an algorithm variant at runtime operator).
Declares a common strategy interface for all variants of this algorithm.
Extract the algorithms into their respective classes one by one, and they must all implement the strategy interface.
Add a member variable in the context class to save a reference to the policy object. Then provide a setter to modify the member variable. The context can only interact with the policy object through the policy interface. If necessary, an interface can be defined to allow the policy to access its data.
The client must associate the context class with the corresponding policy so that the context can complete its main job in the expected manner.
You can switch algorithms within an object at runtime.
You can isolate the implementation of the algorithm from the code that uses the algorithm.
You can use composition instead of inheritance.
Opening and closing principle. You can introduce new strategies without modifying the context.
If your algorithm rarely changes, there is no reason to introduce new classes and interfaces. Using this pattern will only make the program overly complex.
The client must be aware of the differences between strategies - it needs to choose the appropriate strategy.
Many modern programming languages support the function type feature, allowing you to implement different versions of an algorithm in a set of anonymous functions. This way, you use these functions in exactly the same way as using the policy object, without having to resort to additional classes and interfaces to keep your code simple.
The interfaces of the Bridge, Stateful, and Strategy (and to some extent Adapter) patterns are very similar. In fact, they are all based on the composition pattern-that is, delegating work to other objects, but each solves different problems. Patterns aren't just recipes for organizing code in a specific way; you can also use them to discuss the problems they solve with other developers.
Command patterns and strategies look similar because both can parameterize objects with certain behaviors. However, their intentions are very different.
You can use commands to convert any operation into an object. The parameters of the operation will become member variables of the object. You can use transformations to delay the execution of operations, queue operations, save historical commands, or send commands to remote services.
Strategies, on the other hand, can often be used to describe different ways of accomplishing something, allowing you to switch algorithms within the same context class.
Decoration mode allows you to change the appearance of an object, while strategies allow you to change its essence.
The template method pattern is based on the inheritance mechanism: it allows you to change part of the algorithm by extending part of the content in the subclass. Strategies are based on a composition mechanism: you can change part of an object's behavior by providing different strategies for the corresponding behavior. Template methods operate at the class level, so it is static. Policies operate at the object level, thus allowing behavior to be switched at runtime.
State can be thought of as an extension of strategy. Both are based on composition mechanisms: they both change its behavior in different situations by delegating part of the work to "helper" objects. The policy makes these objects completely independent of each other, and they are unaware of the existence of other objects. However, the state pattern does not limit the dependencies between specific states and allows them to change their states in different scenarios.
The above is the detailed content of What is the strategy pattern of java design patterns?. For more information, please follow other related articles on the PHP Chinese website!