xxxxxxxxxx
Strategy pattern is quite useful for implementing a set of related algorithms like compression algorithms, filtering strategies, etc.
The strategy design pattern allows you to create Context classes, which use Strategy implementation classes for applying business rules.
One good example of a Strategy pattern from JDK itself is a Collections.sort() method and the Comparator interface, which is a strategy interface and defines a strategy for comparing objects.
Because of this pattern, we don't need to modify the sort() method (closed for modification) to compare any object; at the same time, we can implement a Comparator interface to define a new comparing strategy (open for extension).
This pattern is actually based upon the open-closed design principle and if you understand that principle then it's quite easy for you to understand the Strategy pattern as well. It's actually better to know about SOLID principles as many design patterns are based upon that.
Read more: https://www.java67.com/2012/09/top-10-java-design-pattern-interview-question-answer.html#ixzz7oR5kWCVQ
xxxxxxxxxx
// Java Strategy pattern
// Abstract Strategy
public interface FlyBehavior {
public void fly();
}
//Concrete Strategy
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {System.out.println("I'm flying!");}
}
//Concrete Strategy
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("I can't fly");
}
}
//Concrete Strategy
public class FlyRocketPowered implements FlyBehavior{
@Override
public void fly() {
System.out.println("I'm flying with a rocket!");
}
}
public abstract class Duck {
// Declare Abstract Strategies, specified in concrete subclasses
FlyBehavior flyBehavior;
public Duck() { }
// Execute stratgies
public void performFly() {flyBehavior.fly();}
// Allow change of strategy at Runtime
public void setFlyBehavior(FlyBehavior fb) {flyBehavior = fb;}
}
public class MallardDuck extends Duck {
public MallardDuck() {
//assign strategy
flyBehavior = new FlyWithWings();
}
}
public class ModelDuck extends Duck {
public ModelDuck() {
// assign strategy
flyBehavior = new FlyNoWay();
}
}
public class Client {
public static void main(String[] args) {
Duck mallard = new MallardDuck();
mallard.performFly();
Duck model = new ModelDuck();
model.performFly();
// change algorithm at runtime
model.setFlyBehavior(new FlyRocketPowered());
model.performFly();
}
}
// I'm flying!
// I can't fly
// I'm flying with a rocket!
The Strategy Design Pattern is used in Java when you want to define a family of interchangeable algorithms or behaviors and make them available to a client code without the client needing to know the implementation details. This pattern is particularly useful in situations where you have multiple ways to perform a specific task and want to encapsulate each algorithm separately. Here are some scenarios where you might consider using the Strategy Design Pattern in Java:
Algorithms Variation:
When you have multiple algorithms or strategies that can be applied to solve a problem, you can encapsulate each algorithm in a separate strategy class. This allows you to easily switch between strategies based on requirements.
Run-Time Selection:
If you need to choose an algorithm at runtime based on dynamic conditions, the Strategy pattern enables you to switch strategies without modifying the client code.
Avoiding Conditional Statements:
If you find that your code has complex conditional statements that determine the behavior of an object, you can use the Strategy pattern to move the behavior into separate strategy classes, making the code cleaner and more maintainable.
Reducing Code Duplication:
If you have similar code appearing in multiple places to handle variations in behavior, you can centralize the behavior by using the Strategy pattern, reducing code duplication.
Testing and Maintenance:
The Strategy pattern promotes separation of concerns, making individual strategies easier to test and maintain. Changes to one strategy do not affect other strategies.
Decoupling:
The Strategy pattern promotes loose coupling between client code and the strategies. Clients only need to know about the strategy interface, not the concrete implementations.
Extensibility:
The Strategy pattern allows you to add new strategies without modifying existing code. This makes your codebase more extensible.
Examples of the Strategy pattern's usage in Java include sorting algorithms (such as bubble sort, quicksort, mergesort), payment gateways with different payment methods, text formatting with various formatting strategies, and more.
By using the Strategy Design Pattern, you can create flexible and maintainable code that adapts to different algorithms or behaviors without introducing complexities and dependencies in your client code.
Strategy pattern is very useful for implementing a family of
algorithms. It is a behavioral design pattern.
With Strategy pattern we can select the algorithm at runtime. We can
use it to select the sorting strategy for data. We can use it to save
files in different formats like- .txt, .csv, .jpg etc.
In Strategy pattern we create an abstraction, which is an interface
through which clients interact with our system. Behind the
abstraction we create multiple implementation of same interface
with different algorithms.
For a client, at runtime we can vary the algorithm based on the type
of request we have received.
So we use Strategy pattern to hide the algorithm implementation
details from client.
In Java Collections.sort() method uses strategy design pattern.
xxxxxxxxxx
public class PayByPayPal implements PayStrategy {
private static final Map<String, String> DATA_BASE = new HashMap<>();
private final BufferedReader READER = new BufferedReader(new InputStreamReader(System.in));
private String email;
private String password;
private boolean signedIn;
static {
DATA_BASE.put("amanda1985", "amanda@ya.com");
DATA_BASE.put("qwerty", "john@amazon.eu");
}
/**
* Collect customer's data.
*/
@Override
public void collectPaymentDetails() {
try {
while (!signedIn) {
System.out.print("Enter the user's email: ");
email = READER.readLine();
System.out.print("Enter the password: ");
password = READER.readLine();
if (verify()) {
System.out.println("Data verification has been successful.");
} else {
System.out.println("Wrong email or password!");
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
private boolean verify() {
setSignedIn(email.equals(DATA_BASE.get(password)));
return signedIn;
}
/**
* Save customer data for future shopping attempts.
*/
@Override
public boolean pay(int paymentAmount) {
if (signedIn) {
System.out.println("Paying " + paymentAmount + " using PayPal.");
return true;
} else {
return false;
}
}
private void setSignedIn(boolean signedIn) {
this.signedIn = signedIn;
}
}