Great question. Problem is that there are many solutions and most of them will work.
I work with MVC a lot, similar situation happens quite often. Especially in the view, when similar rendering needs to happen across some views... but does not really belong to the view.
Let's say we have child class ChildList
that extends BaseList
.
Add a property uiHandler
in the child class. Overload the rendering function, let's say toString()
, and use the uiHandler with your specific UI/Design things.
I wrote a little something, it is in PHP... but you should be able to get an idea. It gives you freedom to chose how your objects will be displayed and flexibility to use specific UIs for specific objects.
Look at the code below, it seems like a lot but int's not that bad.
BaseList
- your base class
BaseListUIExtended
- base class that uses UI, takes optional UI class as constructor parameter. In C# 4 you can use optional, otherwise use 2 constructors.
UIBase
- interface for UI classes...
UIChildSpecific
- UI class
ChildList
- child class that can use UI or not, because of BaseListUIExtended
optional constructor parameter.
Define interface
/**
* Base UI interface
*/
interface IUIBase {
/**
* Renders the Base Class
*
* @param UIBase $obj
* @return string
*/
public function render($obj);
}
Define base classes, child class
//**************************************************************
// 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...
//**************************************************************
// 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>