# 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:

```java
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:

```java
public interface ElevatorIO {
    void setPower(double power);
    double getPosition();
}
```

Then create different implementations:

**Real hardware implementation**

```java
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**

```java
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`

```java
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());
    }
}
```
