Modello del decoratore usando la composizione invece dell'ereditarietà
-
06-07-2019 - |
Domanda
La mia precedente comprensione del motivo del decoratore era che hai ereditato Window
con WindowDecorator
, quindi nei metodi sovrascritti, fai qualche lavoro aggiuntivo prima di chiamare la Window
implementazione di detti metodi. Simile al seguente:
public class Window
{
public virtual void Open()
{
// Open the window
}
}
public class LockableWindow : Window // Decorator
{
public virtual void Open()
{
// Unlock the window
base.Open();
}
}
Tuttavia, in sostanza, questo decodifica la decorazione, quindi come potrebbe essere refactored per usare la composizione invece dell'eredità?
Soluzione
Siamo spiacenti, il mio C # è un po '(OK, molto) arrugginito, quindi potrebbero esserci alcuni errori di sintassi, ma l'idea di base è corretta.
public interface IWindow
{
void Open();
}
public class Window : IWindow
{
public virtual void Open()
{
// Open the window
}
}
public class LockableWindow : IWindow
{
private IWindow _wrappedWindow;
public LockableWindow(IWindow wrappedWindow)
{
_wrappedWindow = wrappedWindow;
}
public virtual void Open()
{
// TODO Unlock window if necessary
_wrappedWindow.open();
}
}
La cosa fondamentale da notare è la nuova interfaccia IWindow
; questo è ciò che ti consente di continuare a usare il polimorfismo.
Altri suggerimenti
Lo scopo del motivo Decorator è migliorare un oggetto con alcune funzionalità (ad esempio aggiungendo il buffering a uno stream) in modo trasparente per il chiamante. Per utilizzarlo nel modo più efficace, si desidera poter scambiare l'implementazione decorata senza il codice di refactoring, il che implica sostanzialmente che è necessario mantenere la gerarchia dell'ereditarietà.
Qual è la tua reale preoccupazione, ovvero cosa significa "codifica la decorazione" veramente meschino? Che tipo di problemi prevedi di voler risolvere? Può darsi che la decorazione non sia proprio l'approccio giusto ...
Devi semplicemente definire LockableWindow un costruttore che prende un'istanza del tipo, Window, che decorerà. Puoi anche farlo tramite le proprietà.
public class Window
{
public virtual void Open()
{
// Open the window
}
}
public class LockableWindow // Decorator
{
private Window window;
public LockableWindow(Window w)
{
window = w;
}
public virtual void Open()
{
// Unlock the window
window.Open();
}
}
La mia comprensione del motivo del decoratore è che ha lo scopo di consentire un miglioramento runtime delle capacità di un oggetto. Nella spiegazione di Wikipedia, si concentrano su uno stack di componenti per questo scopo.
Non parlo affatto C #, quindi questo è (ovviamente) php-ish. Sembra che l'idea corretta sarebbe:
class image{
function open(){ ... }
} //end of class
class decoratedImage extends image{
private goodies=array(); //the alleged 'component stack'
function addGoodie($item){
$this->goodies[]=$item;
}
function open()}{
parent::open();
foreach ($this->goodies as $componentClassName){
$component=new $componentClassName();
$component->apply($this);
}
}
} //end of class
Oh ragazzi esperti, per favore spiegate la disconnessione.