Strategy
What is the Strategy Pattern?
The Strategy Pattern is a behavioral design pattern that enables selecting an algorithm’s behavior at runtime. It defines a family of interchangeable algorithms (strategies), encapsulates each one, and makes them interchangeable within the context they operate in. This promotes flexibility and decouples implementation details from the core logic.
Why Use Strategy in FRC Subsystems?
In robot programming, especially for FRC, subsystems often interact with hardware devices like motors, sensors, or vision systems. However, hardware might change or need to be simulated for testing. The Strategy Pattern lets you:
Swap between real hardware interfaces and simulated/mock interfaces without changing the subsystem logic.
Support multiple hardware implementations (e.g., different motor controllers).
Test your code easily in simulation or on real robots.
Keep subsystem code clean and independent of specific hardware APIs.
Example Use Case: Different IO Implementations for a Subsystem
Imagine an Elevator subsystem that controls a motor and reads encoder positions.
Without Strategy
You might hardcode hardware calls directly inside the subsystem. This makes it hard to swap hardware or test:
public class Elevator {
private TalonSRX motor;
private Encoder encoder;
public Elevator() {
motor = new TalonSRX(1);
encoder = new Encoder(0, 1);
}
public void setPower(double power) {
motor.set(power);
}
public double getPosition() {
return encoder.getDistance();
}
}
Problems:
Can’t easily replace
TalonSRX
with another motor type.Hard to simulate encoder/motor for testing.
Changes in hardware API break subsystem code.
Applying Strategy Pattern
Define an interface that abstracts elevator I/O operations:
public interface ElevatorIO {
void setPower(double power);
double getPosition();
}
Then create different implementations:
Real hardware implementation
public class ElevatorIOReal implements ElevatorIO {
private TalonSRX motor = new TalonSRX(1);
private Encoder encoder = new Encoder(0, 1);
@Override
public void setPower(double power) {
motor.set(power);
}
@Override
public double getPosition() {
return encoder.getDistance();
}
}
Simulated/mock implementation
public class ElevatorIOSim implements ElevatorIO {
private double power;
private double simulatedPosition = 0;
@Override
public void setPower(double power) {
this.power = power;
simulatedPosition += power * 0.1; // simple simulation logic
}
@Override
public double getPosition() {
return simulatedPosition;
}
}
Refactor Elevator subsystem to use ElevatorIO
ElevatorIO
public class Elevator extends Subsystem {
private final ElevatorIO io;
public Elevator(ElevatorIO io) {
this.io = io;
}
public void setPower(double power) {
io.setPower(power);
}
public double getPosition() {
return io.getPosition();
}
// Factory method for easy switching
public static Elevator createReal() {
return new Elevator(new ElevatorIOReal());
}
public static Elevator createSim() {
return new Elevator(new ElevatorIOSim());
}
}
Last updated