I'm not sure which design pattern might help me solve this issue.
I have a class, 'Coordinator', which determines which Worker class should be used - without having to know about all the different types of Workers there are - it just calls a WorkerFactory and acts upon the common IWorker interface.
It then sets the appropriate Worker to work and returns the result of its 'DoWork' method.
This has been fine... up until now; we have a new requirement for a new Worker class, "WorkerB" which requires an additional amount of information i.e. an additional input parameter, in order for it to do its work.
Its like we need an overloaded DoWork method with the extra input parameter...but then all the existing Workers would have to implement that method - which seems wrong as those Workers really dont need that method.
How can I refactor this to keep the Coordinator unaware of which Worker is being used and still allowing each Worker to get the information it requires to do its job but not have any Worker do things it doesn't need to?
There are a lot of existing Workers already.
I don't want to have to change any of the existing concrete Workers to accommodate the requirements of the new WorkerB class.
I thought maybe a Decorator pattern would be good here but I haven't seen any Decorators decorate an object with the same method but different parameters before...
Situation in code:
public class Coordinator { public string GetWorkerResult(string workerName, int a, List<int> b, string c) { var workerFactor = new WorkerFactory(); var worker = workerFactor.GetWorker(workerName); if(worker!=null) return worker.DoWork(a, b); else return string.Empty; } } public class WorkerFactory { public IWorker GetWorker(string workerName) { switch (workerName) { case "WorkerA": return new ConcreteWorkerA(); case "WorkerB": return new ConcreteWorkerB(); default: return null; } } } public interface IWorker { string DoWork(int a, List<int> b); } public class ConcreteWorkerA : IWorker { public string DoWork(int a, List<int> b) { // does the required work return "some A worker result"; } } public class ConcreteWorkerB : IWorker { public string DoWork(int a, List<int> b, string c) { // does some different work based on the value of 'c' return "some B worker result"; } public string DoWork(int a, List<int> b) { // this method isn't really relevant to WorkerB as it is missing variable 'c' return "some B worker result"; } }
IWorker
interface listed the old version, or is that a new version with an added parameter?Coordinator
already had to be changed to accommodate that extra parameter in itsGetWorkerResult
function - that means that the Open-Closed-Principle of SOLID is violated. As a consequence, all the code callingCoordinator.GetWorkerResult
had to be changed also. So look at the place where you call that function: how do you decide which IWorker to request? That may lead to a better solution.