Отличный вопрос. Проблема в том, что существует много решений, и большинство из них будут работать.
Я много работаю с MVC, подобная ситуация случается довольно часто. Особенно в представлении, когда подобный рендеринг должен происходить в некоторых представлениях ... но на самом деле он не принадлежит представлению.
Допустим, у нас есть дочерний класс ChildList
, который расширяет BaseList
.
Добавьте свойство uiHandler
в дочерний класс. Перегрузите функцию рендеринга, скажем, toString()
, и используйте uiHandler со своими специфическими элементами пользовательского интерфейса / дизайна.
Я кое-что написал, это на PHP ... но у вас должна получиться идея. Это дает вам свободу выбора способа отображения ваших объектов и гибкость в использовании определенных интерфейсов для определенных объектов.
Посмотрите на приведенный ниже код, он выглядит много, но int не так уж и плох.
BaseList
- ваш базовый класс
BaseListUIExtended
- базовый класс, который использует пользовательский интерфейс, принимает необязательный класс пользовательского интерфейса в качестве параметра конструктора. В C # 4 вы можете использовать необязательные, в противном случае используйте 2 конструктора.
UIBase
- интерфейс для классов пользовательского интерфейса ...
UIChildSpecific
- UI класс
ChildList
- дочерний класс, который может использовать пользовательский интерфейс или нет, поскольку BaseListUIExtended
необязательный параметр конструктора.
Определить интерфейс
/**
* Base UI interface
*/
interface IUIBase {
/**
* Renders the Base Class
*
* @param UIBase $obj
* @return string
*/
public function render($obj);
}
Определение базовых классов, дочерний класс
//**************************************************************
// Define Base Classes
//**************************************************************
/**
* Base Class
*/
class BaseList {
/**
* List of items
* @var array
*/
protected $_items = array();
/**
* Gets collection of items
*
* @return array
*/
public function getItems() {
return $this->_items;
}
/**
* Adds new item to the list
* @param object $item
*/
public function add($item) {
$this->_items[] = $item;
}
/**
* Displays object
*/
public function display() {
echo $this->toString();
}
/**
* To String
*/
public function __toString() {
// Will output list of elements separated by space
echo implode(' ', $this->_items);
}
}
/**
* Extended BaseList, has UI handler
* This way your base class stays the same. And you
* can chose how you create your childer, with UI or without
*/
class BaseListUIExtended extends BaseList {
/**
* UI Handler
* @var UIBase
*/
protected $_uiHandler;
/**
* Default Constructor
*
* @param UIBase Optional UI parameter
*/
public function __construct($ui = null) {
// Set the UI Handler
$this->_uiHandler = $ui;
}
/**
* Display object
*/
public function display() {
if ($this->_uiHandler) {
// Render with UI Render
$this->_uiHandler->render($this);
} else {
// Executes default BaseList display() method
// in C# you'll have base:display()
parent::display();
}
}
}
//**************************************************************
// Define UI Classe
//**************************************************************
/**
* Child Specific UI
*/
class UIChildSpecific implements UIBase {
/**
* Overload Render method
*
* Outputs the following
* <strong>Elem 1</strong><br/>
* <strong>Elem 2</strong><br/>
* <strong>Elem 3</strong><br/>
*
* @param ChildList $obj
* @return string
*/
public function render($obj) {
// Output array for data
$renderedOutput = array();
// Scan through all items in the list
foreach ($obj->getItems() as $text) {
// render item
$text = "<strong>" . strtoupper(trim($text)) . "</strong>";
// Add it to output array
$renderedOutput[] = $text;
}
// Convert array to string. With elements separated by <br />
return implode('<br />', $renderedOutput);
}
}
//**************************************************************
// Defining Children classes
//**************************************************************
/**
* Child Class
*/
class ChildList extends BaseListUIExtended {
// Implement's logic
}
Тестирование ...
//**************************************************************
// TESTING
//**************************************************************
// Test # 1
$plainChild = new ChildList();
$plainChild->add("hairy");
$plainChild->add("girl");
// Display the object, will use BaseList::display() method
$plainChild->display();
// Output: hairy girl
// Test # 2
$uiChild = new ChildList(new UIChildSpecific());
$uiChild->add("hairy");
$uiChild->add("girl");
// Display the object, will use BaseListUIExtended::display() method
$uiChild->display();
// Output: <strong>hairy</strong><br /><strong>girl</strong>