Bonne question. Le problème est qu'il existe de nombreuses solutions et la plupart fonctionneront.
Je travaille beaucoup avec MVC, une situation similaire se produit assez souvent. Surtout dans la vue, quand un rendu similaire doit se produire sur certaines vues ... mais n'appartient pas vraiment à la vue. Disons que nous avons la classe enfant ChildList
qui s'étend BaseList
. Ajouter une propriété uiHandler
dans la classe enfant. Surchargez la fonction de rendu, disons toString()
, et utilisez le uiHandler avec vos éléments d'interface utilisateur/conception spécifiques.
J'ai écrit un petit quelque chose, c'est en PHP ... mais vous devriez pouvoir vous faire une idée. Il vous donne la liberté de choisir comment vos objets seront affichés et la flexibilité d'utiliser des interfaces utilisateur spécifiques pour des objets spécifiques. Regardez le code ci-dessous, il semble que beaucoup mais int n'est pas si mal.
BaseList
- votre classe
BaseListUIExtended
de base - classe de base qui utilise l'interface utilisateur, se classe UI en option en tant que paramètre constructeur. En C# 4 vous pouvez utiliser optionnel, sinon utilisez 2 constructeurs.
UIBase
- Interface pour les classes de l'interface utilisateur ...
UIChildSpecific
- classe UI
ChildList
- classe enfant qui peut utiliser l'interface utilisateur ou non, en raison de BaseListUIExtended
paramètre du constructeur en option.
Définir l'interface
/**
* Base UI interface
*/
interface IUIBase {
/**
* Renders the Base Class
*
* @param UIBase $obj
* @return string
*/
public function render($obj);
}
Définir les classes de base, classe enfant
//**************************************************************
// 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
}
test ...
//**************************************************************
// 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>
+1 pour Poilu Fille – demoncodemonkey
Salut, ont à présent regardé votre exemple un peu plus et c'est une bonne solution, MAIS ... cela ne fonctionne pas dans des solutions plus complexes. Votre solution est élégante lorsque tous les éléments sont des chaînes ou d'autres types de valeur, mais si les objets de la liste sont des objets complexes qui nécessitent des méthodes de rendu encore plus complexes, cela ne sera pas si agréable. "dans la méthode render dans les implémentations IUIBase, c'est ce que je veux contourner. – Marcus
@Marcus, d'après ma compréhension de votre question que vous vouliez rendre des objets, mais ne voulait pas garder UI/Design séparé. C'est exactement ce que fait mon exemple de code. Chaque classe aurait son propre gestionnaire d'interface utilisateur, cela séparera l'interface utilisateur de Logic (un peu comme 'view' et' controller' dans MVC). Les cordes ont été utilisées pour la simplicité. Vous pouvez créer 'Container' et positionner tous les objets (boutons, étiquettes, textboxes) avec le conteneur. De toute façon, vous devrez coder la logique UI/Design soit dans votre classe (code désordonné + difficile à maintenir) ou dans une sorte de gestionnaire d'interface utilisateur (code plus propre + plus facile à maintenir). – Alex