Ich bin mir nicht sicher, welches Entwurfsmuster mir bei der Lösung dieses Problems helfen könnte.
Ich habe eine Klasse, 'Coordinator', die festlegt, welche Worker-Klasse verwendet werden soll - ohne über die verschiedenen Arten von Workern Bescheid wissen zu müssen -, ruft einfach eine WorkerFactory auf und reagiert auf die gemeinsame IWorker-Schnittstelle.
Anschließend setzt es den entsprechenden Worker auf Arbeit und gibt das Ergebnis seiner DoWork-Methode zurück.
Das war in Ordnung ... bis jetzt; Wir haben eine neue Anforderung für eine neue Worker-Klasse, "WorkerB", die eine zusätzliche Menge an Informationen benötigt, dh einen zusätzlichen Eingabeparameter, damit sie ihre Arbeit erledigen kann.
Es ist, als ob wir eine überladene DoWork-Methode mit dem zusätzlichen Eingabeparameter benötigen ... aber dann müssten alle vorhandenen Worker diese Methode implementieren - was falsch erscheint, da diese Worker diese Methode wirklich nicht benötigen.
Wie kann ich dies umgestalten, damit der Koordinator nicht weiß, welcher Mitarbeiter verwendet wird, und jedem Mitarbeiter weiterhin die Informationen zur Verfügung stellt, die er für seine Arbeit benötigt, ohne dass ein Mitarbeiter Dinge tut, die er nicht benötigt?
Es gibt bereits viele existierende Arbeiter.
Ich möchte keinen der vorhandenen konkreten Worker ändern müssen, um den Anforderungen der neuen WorkerB-Klasse gerecht zu werden.
Ich dachte, vielleicht wäre ein Dekorationsmuster hier gut, aber ich habe noch nie gesehen, dass Dekorateure ein Objekt mit derselben Methode, aber unterschiedlichen Parametern dekorieren ...
Situation im 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";
}
}
Coordinator
musste bereits geändert werden, um diesen zusätzlichen Parameter in seiner GetWorkerResult
Funktion zu berücksichtigen - das bedeutet, dass das Open-Closed-Prinzip von SOLID verletzt wird. Infolgedessen mussten auch alle Codeaufrufe Coordinator.GetWorkerResult
geändert werden. Schauen Sie sich also den Ort an, an dem Sie diese Funktion aufrufen: Wie entscheiden Sie, welchen IWorker Sie anfordern möchten? Das kann zu einer besseren Lösung führen.
IWorker
Schnittstelle in der alten Version aufgeführt oder handelt es sich um eine neue Version mit einem hinzugefügten Parameter?