Я не впевнений, яка модель дизайну може допомогти мені вирішити цю проблему.
У мене є клас «Координатор», який визначає, який клас Worker слід використовувати - не знаючи про всі різні типи робітників - він просто викликає WorkerFactory і діє за загальним інтерфейсом IWorker.
Потім він встановлює відповідного Worker для роботи та повертає результат свого методу "DoWork".
Це було добре ... досі; у нас є нова вимога до нового класу Worker, "WorkerB", який вимагає додаткової кількості інформації, тобто додаткового вхідного параметра, щоб він міг виконувати свою роботу.
Начебто нам потрібен перевантажений метод DoWork з додатковим вхідним параметром ... але тоді всі існуючі Робітники повинні були реалізувати цей метод - що здається неправильним, оскільки цим Робітникам дійсно не потрібен цей метод.
Як я можу це зробити рефактор, щоб Координатор не знав про те, який працівник використовується, і все ж дозволяв кожному Працівнику отримати інформацію, необхідну для виконання своєї роботи, але не маючи жодного Робітника робити те, що йому не потрібно?
Вже є багато існуючих Робітників.
Мені не хочеться змінювати жодного з існуючих конкретних Workers, щоб вони відповідали вимогам нового класу WorkerB.
Я подумав, що, можливо, тут добре підійде візерунок «Декоратор», але я ще не бачив, щоб декоративники прикрашали об’єкт тим самим методом, але з іншими параметрами раніше ...
Ситуація в коді:
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функції - це означає, що принцип відкритого закритого принципу SOLID порушений. Як наслідок, також Coordinator.GetWorkerResultслід було змінити всі виклики коду . Отже, подивіться на місце, де ви викликаєте цю функцію: як ви вирішите, до якого IWorker звернутися? Це може призвести до кращого рішення.
IWorkerінтерфейсі вказана стара версія чи це нова версія з доданим параметром?