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. Furthermore, you want the code to load implementations dynamically, not via compile-time selection. It is better to bury this logic in an object instead of one long method. I recommend the following components:
Each "method" or algorithm, i.e. each "supplier" in your example, has a pair of classes:
An actual supplier that does whatever your problem needs it to do.
A service provider that determines if this particular supplier can handle the input, and is able to create the supplier.
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 ServiceProvider { boolean canHandle(Input i); object newHandler(object o); } class Factory { List<ServiceProvider> sps = new ArrayList<>(); public static void register(ServiceProvider sp) { sps.add(sp); } public static Supplier getSupplier(Input i) { for (ServiceProvider sp in sps) { if (sp.canHandle(i)) { return sp.newHandler(i); } } return null; } } Notes:
This replaces
switchwith 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.
Service providers need to register themselves. The specific mechanism to do this is dependent on the language (your question is not tagged with a specific language).
Java can use the Service Provider Interface.
C++, static linking: just call an initialization function to set this up before use.
C++, dynamic linking: set it up in DllMainDllMain or the equivalent entry point for your platform.
C#: you can implement the IServiceProvider interface.