What you are looking for is not a singleton, but a factory. The reason is you have a single object that figures out which logic to execute, then executes it. As you say in your comment, it is functionally similar to a `switch` statement: figure out which branch to execute, then execute it.
That works fine if your logic is simple, but once it grows in complexity, the `switch` or cascaded `if` grows cumbersome. It is better to bury this logic in an object instead of one long method. I recommend the following components:
* One class for each "method" or algorithm, i.e. each "supplier" in your example. Each class can determine if it is able to handle the given input data (e.g. based on the date ranges or quantities)
* One class that represents input data for easy passing between methods (no overloading necessary).
* One factory class that accepts input and returns an object capable of processing it.
Example in pseudocode:
class Input {
public DateRange range;
public int quantity;
}
interface Supplier {
boolean canHandle(Input i);
object handle(object o);
}
// Classes SupplierA and SupplierB et. al. implement Supplier.
class Factory {
List<Supplier> suppliers = new ArrayList<>(new SupplierA(), new SupplierB(), ...);
public static Supplier getSupplier(Input i) {
for (Supplier s in suppliers) {
if (s.canHandle(i)) {
return s;
}
}
return null;
}
}
Notes:
* This replaces `switch` with dynamic dispatch via traversing the list and finding an instance that can handle the input.
* This is a simple example to give you the idea. Depending on the specific problem at hand, it may be better to use a hash table or other data structure.
* This assumes each `Supplier` has no state at the object level. If this is not true, you will need to store the type in the list or hashtable and return a new instance each time to be safe.