Відповідь нижче неправильна, але я буду тримати її для того, щоб інші дізналися від неї (див. Нижче)
У ExampleA, ви можете використовувати один і той же Configекземпляр для кількох класів. Однак якщо Configу всій програмі має бути лише один екземпляр, розгляньте можливість застосування шаблону Singleton, Configщоб уникнути появи декількох екземплярів Config. І якщо Configце Singleton, ви можете зробити наступне:
class ExampleA
{
private $config;
public function __construct()
{
$this->config = Config->getInstance();
}
}
$exampleA = new ExampleA();
З ExampleBіншого боку, ви завжди отримаєте окремий екземпляр Configдля кожного екземпляра ExampleB.
Яку версію слід застосувати насправді, залежить від того, як програма буде обробляти екземпляри Config:
- якщо кожен екземпляр
ExampleXповинен мати окремий екземпляр Config, перейдіть з ExampleB;
- якщо кожен екземпляр
ExampleXбуде ділити один (і лише один) екземпляр Config, використовувати ExampleA with Config Singleton;
- якщо екземпляри
ExampleXможуть використовувати різні екземпляри Config, дотримуйтесь ExampleA.
Чому перетворення Configв Singleton є неправильним:
Я мушу визнати, що про взірці Сінглтона я дізнався лише вчора (читаючи голову Першої книги дизайнерських моделей). Наївно я пішов і застосував це для цього прикладу, але, як багато хто вказував, один із способів - інший (деякі були більш кричущими і казали лише "ти робиш це неправильно!"), Це не дуже гарна ідея. Отже, щоб не допустити інших помилок, які я щойно робив, тут викладено короткий опис того, чому шаблон Singleton може бути шкідливим (на основі коментарів та того, що я виявив, що його гуглить):
Якщо ExampleAотримає власне посилання на Configекземпляр, класи будуть щільно з'єднані. Не буде можливості мати примірник ExampleAвикористання іншої версії Config(скажімо, підкласу). Це жахливо, якщо ви хочете протестувати ExampleAза допомогою макетного екземпляра, Configоскільки це не існує для цього ExampleA.
Передумова існуватиме один, і лише один, екземпляр, Configможливо, зараз є , але ви не завжди можете бути впевнені, що те саме відбудеться і в майбутньому . Якщо в якийсь пізній момент виявиться, що Configбажано декілька екземплярів , немає можливості досягти цього, не переписавши код.
Незважаючи на те, що один-єдиний екземпляр Config, можливо, правдивий на всю вічність, може статися так, що ви хочете мати можливість використовувати якийсь підклас Config(при цьому, маючи лише один примірник). Але, так як код безпосередньо отримує екземпляр через getInstance()з Config, який являє собою staticметод, немає ніякого способу , щоб отримати підклас. Знову код потрібно переписати.
Те, що ExampleAвикористовує, Configбуде приховано, принаймні, лише переглядаючи API ExampleA. Це може бути або не бути поганою справою, але особисто я відчуваю, що це відчуває себе недоліком; наприклад, при підтримці не існує простого способу з’ясувати, на які класи впливатимуть зміни, Configне вивчаючи впровадження будь-якого іншого класу.
Навіть якщо факт ExampleAвикористання Singleton Config сам по собі не є проблемою, він все ж може стати проблемою з точки зору тестування. Об'єкти Singleton матимуть стан, який зберігатиметься до припинення роботи програми. Це може бути проблемою при запуску одиничних тестів, оскільки ви хочете, щоб один тест був ізольований від іншого (тобто те, що виконавши один тест, не повинно впливати на результат іншого). Щоб виправити це, об'єкт Singleton повинен бути знищений між кожним тестовим запуском (можливо, доведеться перезапустити всю програму), що може зайняти багато часу (не кажучи вже про стомлювальний і дратівливий).
Сказавши це, я радий, що я допустив цю помилку тут, а не в реалізації реальної заявки. Насправді я фактично розглядав можливість переписати свій останній код, щоб використовувати шаблон Singleton для деяких класів. Хоча я міг би відновити зміни (звичайно, все зберігається у SVN), я все одно витратив би час на це.