Припустимо, існує Page
клас, який представляє набір вказівок для рендерінгу сторінки. І припустимо, існує Renderer
клас, який знає, як візуалізувати сторінку на екрані. Можна структурувати код двома різними способами:
/*
* 1) Page Uses Renderer internally,
* or receives it explicitly
*/
$page->renderMe();
$page->renderMe($renderer);
/*
* 2) Page is passed to Renderer
*/
$renderer->renderPage($page);
Які плюси і мінуси кожного підходу? Коли буде краще? Коли інший буде кращим?
Передумови
Щоб додати трохи більше фону - я знаходжу себе, використовуючи обидва підходи в одному і тому ж коді. Я використовую сторонню бібліотеку PDF під назвою TCPDF
. Десь у моєму коді я повинен мати таке, щоб PDF-рендерінг працював:
$pdf = new TCPDF();
$html = "some text";
$pdf->writeHTML($html);
Скажіть, я хочу створити представлення сторінки. Я можу створити шаблон, який містить інструкції, щоб зробити фрагмент сторінки PDF таким чином:
/*
* A representation of the PDF page snippet:
* a template directing how to render a specific PDF page snippet
*/
class PageSnippet
{
function runTemplate(TCPDF $pdf, array $data = null): void
{
$pdf->writeHTML($data['html']);
}
}
/* To be used like so */
$pdf = new TCPDF();
$data['html'] = "some text";
$snippet = new PageSnippet();
$snippet->runTemplate($pdf, $data);
1) Зауважте тут, що $snippet
працює сам , як у моєму першому прикладі коду. Він також повинен знати і бути знайомим $pdf
і з будь-яким, $data
щоб він працював.
Але я можу створити такий PdfRenderer
клас:
class PdfRenderer
{
/**@var TCPDF */
protected $pdf;
function __construct(TCPDF $pdf)
{
$this->pdf = $pdf;
}
function runTemplate(PageSnippet $template, array $data = null): void
{
$template->runTemplate($this->pdf, $data);
}
}
і тоді мій код перетворюється на це:
$renderer = new PdfRenderer(new TCPDF());
$renderer->runTemplate(new PageSnippet(), array('html' => 'some text'));
2) Тут $renderer
приймаються PageSnippet
і всі $data
необхідні для нього роботи. Це схоже на мій другий приклад коду.
Отже, незважаючи на те, що рендер отримує фрагмент сторінки, всередині рендерера фрагмент все ще працює сам . Тобто, обидва підходи є в грі. Я не впевнений, чи можете ви обмежити використання OO лише одним або лише іншим. Обидва можуть знадобитися, навіть якщо ви маскуєте одне за одним.