Я не уверен, какой шаблон проектирования может помочь мне решить эту проблему.
У меня есть класс Coordinator, который определяет, какой класс Worker должен использоваться - без необходимости знать обо всех различных типах Workers - он просто вызывает WorkerFactory и действует на общий интерфейс IWorker.
Затем он устанавливает соответствующий Worker и возвращает результат его метода DoWork.
Это было хорошо ... до сих пор; у нас есть новое требование для нового класса Worker, «WorkerB», для которого требуется дополнительный объем информации, то есть дополнительный входной параметр, для выполнения своей работы.
Это похоже на то, что нам нужен перегруженный метод DoWork с дополнительным входным параметром ... но тогда все существующие работники должны будут реализовать этот метод - что кажется неправильным, поскольку этим рабочим действительно не нужен этот метод.
Как я могу реорганизовать это так, чтобы Координатор не знал, какой работник используется, и при этом позволял каждому работнику получать информацию, необходимую ему для выполнения своей работы, но не заставлять какого-либо работника делать то, что ему не нужно?
Уже существует много рабочих.
Я не хочу менять ни одного из существующих конкретных рабочих, чтобы соответствовать требованиям нового класса WorkerB.
Я подумал, может быть, здесь хорошо подойдет шаблон Decorator, но я не видел, чтобы декораторы украшали объект одним и тем же методом, но разными параметрами раньше ...
Ситуация в коде:
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
уже пришлось изменить, чтобы учесть этот дополнительный параметр в своей GetWorkerResult
функции - это означает, что принцип Open-Closed-принцип SOLID нарушается. Как следствие, весь код вызова Coordinator.GetWorkerResult
должен был быть изменен также. Посмотрите, где вы вызываете эту функцию: как вы решаете, какой IWorker запрашивать? Это может привести к лучшему решению.
IWorker
интерфейсе старая версия или это новая версия с добавленным параметром?