TL;DR
In apex, is it possible to get around the use of if-else/switch statements to supply unique code via an enum or other parameter? Something like storing functions or class instances in maps or enums?
Background
I am working on a calculator program for a Udemy course assignment. The assignment asks us to modify an existing Calculator class to reduce the amount of if-else/switch statements. The original project was in Typescript, and I was able to convert it to Java via support with this stack overflow question. I'm now attempting to do convert the functionality to Apex.
In Typescript, my solution was something like this:
Calculator Class's execute
method:
execute(operation: OperationType, newValue: number) {
let newOperation = generateOperation(operation, this._currentValue, newValue);
this._currentValue = newOperation.calculate();
this._operations.push(newOperation);
return this;
}
Source for generateOperation
method:
const operationGenerationMapper = new Map([
[OperationType.addition, AdditionOperation],
[OperationType.subtraction, SubtractionOperation],
[OperationType.multiplication, MultiplicationOperation],
[OperationType.division, DivisionOperation],
]);
export function generateOperation(
operationType: OperationType,
currentValue: number,
newValue: number
): any {
let newOperation: Operation;
for (let [key, value] of operationGenerationMapper) {
if (operationType == key) {
return new value(currentValue, newValue);
}
}
return null;
}
In Java, my solution was like this:
Calculator execute
class:
public Calculator execute(OperationType operationType, float newValue) {
Operation newOperation = new Operation(this.currentValue, operationType, newValue);
this.currentValue = newOperation.calculate();
operations.add(newOperation);
return this;
}
OperationType
enum:
public enum OperationType {
add("added to") {
public float calculate(float value1, float value2){
return value1 + value2;
}
},
subtract("subtracted from") {
public float calculate(float value1, float value2){
return value1 - value2;
}
},
multiply("multiplied by") {
public float calculate(float value1, float value2){
return value1 * value2;
}
},
divide("divided by") {
public float calculate(float value1, float value2){
return value1 / value2;
}
};
public final String joinerText;
OperationType(String joinerText){
this.joinerText = joinerText;
}
public abstract float calculate(float value1, float value2);
}
Question
How can I create a structure in Apex that allows for a variable parameter to come in (such as a string or enum) and unique functionality being returned (e.g. addition, subtraction), without relying on if-else/switch statements. My reason for wanting to avoid these statements is to see if apex supports a solution that adheres to the Open/Closed SOLID principle, and just more scalable code in general.
An example of what the "problem" code could look like:
public Calculator execute(OperationType operationType, float newValue) throws Exception {
switch (operationType) {
case add:
return this.currentValue + newValue;
break;
case subtract:
return this.currentValue - newValue;
break;
case multiply:
return this.currentValue * newValue;
break;
case divide:
return this.currentValue / newValue
break;
default:
throw new Exception("Invalid operation type");
}
}
Thoughts/Ideas
The only apex-based solution I can think of is to just make a new method for each new calculation type (add()
, subtract()
, etc.), but that doesn't really answer my original question. One could also offload the switch statement to another class or function, but that just moves the switch, it doesn't eliminate it.