Strategy Design Pattern

I share my learnings here. Thanks for reading.
The Strategy Pattern allows a client to choose an algorithm from a family of algorithms at runtime, without altering the code that uses the algorithm.
If the children of a parent class have the same implementations then the code is redundant. To avoid the duplication of the code it is better to create a separate concrete class that has this implementation.
Example: Take into account the subsequent example, which enjoys considerable popularity within the context of this particular pattern.
Without a Strategy Design Pattern
package WithoutStrategy;
public class Vehicle {
public void drive(){
System.out.println("Normal drive capability");
}
}
public class GoodsVehicle extends Vehicle{
}
public class PassengerVehicle extends Vehicle{
}
//Advanced Capability
public class OffRoadVehicle extends Vehicle{
public void drive() {
System.out.println("sports drive capability");
}
}
public class SportsVehicle extends Vehicle{
public void drive(){
System.out.println("Sports drive capability");
}
}
In the above code example parent class is Vehicle has drive() functionality. Two child classes have sports drive capability and the remaining 2 have normal drive capability same as the parent. In this, there is a duplication of code for SportsVehicle and OffRoadVehicle to counter this will use the following approach.
With Strategy Pattern
package WithStrategy.Strategy;
public interface DriveStrategy {
public void drive();
}
public class NormalDriveStratagey implements DriveStrategy{
@Override
public void drive() {
System.out.println("Normal Drive Strategy");
}
}
public class SportsDriveStrategy implements DriveStrategy{
@Override
public void drive() {
System.out.println("Sports drive strategy");
}
}
This separated the code into an interface since the drive capability is of 2 forms hence interface is compulsory. The 2 implementations are normal and sports drive strategy.
package WithStrategy;
import WithStrategy.Strategy.DriveStrategy;
public class Vehicle {
DriveStrategy driveStrategy;
public Vehicle(DriveStrategy driveStrategy) {
this.driveStrategy = driveStrategy;
}
public void drive() {
driveStrategy.drive();
}
}
public class SportsVehicle extends Vehicle{
public SportsVehicle(){
super(new SportsDriveStrategy());
}
}
public class PassengerVehicle extends Vehicle{
public PassengerVehicle(){
super(new NormalDriveStratagey());
}
}
public class OffRoadVehicle extends Vehicle{
public OffRoadVehicle(){
super(new SportsDriveStrategy());
}
}
public class GoodsVehicle extends Vehicle {
public GoodsVehicle() {
super(new NormalDriveStratagey());
}
}
Conclusion: In summary, when code repetition occurs, it's advisable to generate a new class. Subsequently, replace the duplicated code with objects of the newly created class. For enhanced adaptability, consider incorporating an interface within that class. This approach enables seamless accommodation of diverse algorithms or versions in the future.