Station Status Board – Task 7

The subsystem-specific features you added in the previous task have proven valuable. The reactor team appreciates the shutdown warnings, the power team uses the trend analysis for maintenance scheduling, and the life support team relies on the per-person oxygen calculations. However, as more teams request similar specialized features, the conditional logic in your code has grown unwieldy. The chief engineer wants to show you a better way to organize this type of code.

She explains that the current approach treats all subsystems as identical, then adds special cases based on their names. "But that's not quite accurate," she says. "A reactor monitor and a power monitor are both subsystem monitors—they share the core monitoring functionality—but they're also distinct types with their own specific behaviors. There's a programming technique called inheritance that lets us express this relationship directly."

She pulls up an example from the station's personnel system. The crew management software models different types of station personnel:

class CrewMember {
    String name;
    String id;
    String assignment;
    
    CrewMember(String name, String id, String assignment) {
        this.name = name;
        this.id = id;
        this.assignment = assignment;
    }
    
    void displayInfo() {
        System.out.println(name + " [" + id + "]");
        System.out.println("Assignment: " + assignment);
    }
}

class Engineer extends CrewMember {
    String specialization;
    
    Engineer(String name, String id, String assignment, String specialization) {
        super(name, id, assignment);
        this.specialization = specialization;
    }
    
    void displayInfo() {
        super.displayInfo();
        System.out.println("Engineering specialty: " + specialization);
    }
}

class MedicalStaff extends CrewMember {
    String certification;
    
    MedicalStaff(String name, String id, String assignment, String certification) {
        super(name, id, assignment);
        this.certification = certification;
    }
    
    void displayInfo() {
        super.displayInfo();
        System.out.println("Medical certification: " + certification);
    }
}

"See how Engineer and MedicalStaff extend CrewMember?" she explains. "They inherit all the common fields and methods, but they can add their own specific data and override methods to add specialized behavior. The base class handles what's common to everyone, and the subclasses handle what's unique to each type."

Your task is to refactor your monitoring system using inheritance. Create a base class called SubsystemMonitor that contains the fields and methods common to all subsystems. Then create specialized subclasses for the subsystems that need custom behavior:

For subsystems that don't need specialized behavior (Navigation, ThermalRegulation, WasteRecycling, CommArray, DockingClamps), you can create instances of the base SubsystemMonitor class directly.

The status file remains unchanged:

ReactorCooling 42% NORMAL 35% 58% 35% 127 14:23
PowerDistribution 119V NORMAL 115V 124V 117V 134 14:23
LifeSupport 198000ppm NORMAL 195000ppm 205000ppm 195000ppm 128 14:23
Navigation 0.02deg WARNING 0.00deg 0.08deg 0.05deg 131 14:23
ThermalRegulation 18C NORMAL 16C 22C 15C 129 14:23
WasteRecycling 87% NORMAL 82% 95% 80% 126 14:23
CommArray 94% NORMAL 89% 98% 85% 133 14:23
DockingClamps 3201kPa NORMAL 3150kPa 3280kPa 3100kPa 130 14:23

When creating your HashMap, you'll now store different types of monitor objects:

HashMap<String, SubsystemMonitor> subsystems = new HashMap<>();
subsystems.put("ReactorCooling", new ReactorMonitor(...));
subsystems.put("PowerDistribution", new PowerMonitor(...));
subsystems.put("LifeSupport", new LifeSupportMonitor(...));
subsystems.put("Navigation", new SubsystemMonitor(...));
// etc.

Because all these classes extend SubsystemMonitor, they can all be stored in the same HashMap and you can call displayDetails() on any of them. When you call this method, Java will automatically use the overridden version from the specific subclass if one exists, giving you the specialized behavior without any conditional logic.

The output should remain the same as Task 6:

Enter subsystem name (or 'quit' to exit): ReactorCooling
ReactorCooling: 42% [NORMAL]
  Range: 35% to 58%
  Critical threshold: 35%
  Measurements recorded: 127
  Last updated: 14:23

Enter subsystem name (or 'quit' to exit): PowerDistribution
PowerDistribution: 119V [NORMAL]
  Range: 115V to 124V
  Critical threshold: 117V
  Measurements recorded: 134
  Last updated: 14:23
  ?? Voltage trending downward - schedule maintenance check

Enter subsystem name (or 'quit' to exit): quit
Session ended.

As you implement this, notice how the code becomes more organized. The base class contains everything that's common—reading storage, basic display formatting, data management. Each specialized class focuses only on its unique additions. There are no more name-checking conditionals scattered through your code. Instead, the type system itself expresses which monitors have special behaviors. When a new subsystem needs custom features, you create a new subclass rather than adding another conditional branch.

The chief engineer is pleased with this final refactoring. "This is how the station's major systems are organized," she says. "Common functionality in base classes, specialized behavior in subclasses. It scales much better than conditionals as the system grows." She mentions that you'll encounter this pattern throughout the station's codebase as you work on more complex systems.