Affronto un problema se utilizzare un decoratore o un modello di facciata per soddisfare le mie esigenze.
Immagina che un cliente voglia riprodurre un video. Può usare l'interfaccia
public interface IVideoPlayer
{
// Prepares everything to set up and plays the video
void Play();
}
Il client non dovrebbe preoccuparsi della preparazione, quindi il riepilogo del metodo dell'interfaccia afferma che la preparazione è fatta dal metodo Play()
.
La preparazione può includere cose diverse come la connessione a Internet, l'accesso al servizio e così via. Esistono diverse fasi di preparazione per diversi sistemi.
Modello di facciata
Potrei implementare IVideoPlayer
usando il modello di facciata come segue
VideoPlayerFacade : IVideoPlayer
{
ctor(...)
void Play()
{
_internetConnection.Connect();
_loginService.Login();
_actualVideoPlayer.Play();
}
}
Ciò che non mi piace di questo approccio:
- La preparazione (connessione, accesso) sembra più un'aggiunta all'algoritmo di gioco effettivo, che mi porta più al modello di decoratore. Capisco piuttosto il modello di facciata per comporre alcuni passaggi "di livello uguale" per raggiungere un obiettivo comune, come
CreateCar()
delegando aCreateEngine()
,CreateCarBody()
e così via. - Affronto un problema di denominazione perché l'interfaccia del tipo di
_actualVideoPlayer
implementazioni potrebbe anche essere denominataIVideoPlayer
, perché è il vero riproduttore video, che mi guida anche al modello di decoratore. Avrei bisogno di due interfacce quasi identiche (una con e una senza preparazione) con nomi abbastanza simili, che al momento non riesco a immaginare.
Schema decoratore
IVideoPlayer
potrebbe essere implementato con l'algoritmo di riproduzione effettivo come segue
VideoPlayer : IVideoPlayer
{
void Play()
{
// do stuff and algorithms
}
}
La preparazione potrebbe essere eseguita in un decoratore come segue
PreparatingVideoPlayer : IVideoPlayer
{
ctor(...)
void Play()
{
_internetConnection.Connect();
_loginService.Login();
_decoratee.Play();
}
}
Ciò che non mi piace di questo approccio:
-
In realtà
VideoPlayer
viola l'LSP perché non è conforme all'interfaccia non eseguendo tutta la preparazione nel metodoPlay()
, il che mi porta piuttosto al modello di facciata. O non viola l'LSP perché sarà sempre decorato daPreparatingVideoPlayer
quando viene iniettato nel sistema? -
Cosa succede se un altro cliente desidera riprodurre video senza preparazione (perché il client sa che tutto è preparato o preparato tutto da solo)? Non sarebbe in grado di farlo perché lasciare che
IVideoPlayer
venga iniettato genererà semprePreparatingVideoPlayer
, il che mi porterebbe di nuovo al modello di facciata.
Conclusione
Quindi quale modello è più appropriato o questi modelli sono appropriati? I miei dubbi sono validi?