I face an issue if to use a decorator or facade pattern to accomplish my needs.
Imagine a client wants to play a video. He can use the interface
public interface IVideoPlayer
{
// Prepares everything to set up and plays the video
void Play();
}
The client should not be concerned with the preparation, so the interface's method's summary states that preparation is done by the Play()
method.
Preparation may include different things like connecting to the internet, logging in to the service and so on. There are different preparation steps for different systems.
Facade pattern
I could implement IVideoPlayer
using the facade pattern as follows
VideoPlayerFacade : IVideoPlayer
{
ctor(...)
void Play()
{
_internetConnection.Connect();
_loginService.Login();
_actualVideoPlayer.Play();
}
}
What I dislike with this approach:
- The preparation (connecting, logging in) seems more like an addition to the actual playing algorithm, which leads me more to the decorator pattern. I rather understand the facade pattern to compose some "equal level" steps to achieve a common goal, like
CreateCar()
delegating toCreateEngine()
,CreateCarBody()
and so on. - I face a naming issue because the interface the type of
_actualVideoPlayer
implements could also be namedIVideoPlayer
, because it IS the actual video player, which also guides me to the decorator pattern. I would need two almost identical interfaces (one with and one without preparation) with quite similar names, which I cannot imagine at the moment.
Decorator pattern
IVideoPlayer
could be implemented with the actual playing algorithm as follows
VideoPlayer : IVideoPlayer
{
void Play()
{
// do stuff and algorithms
}
}
The preparation could be done in a decorator as follows
PreparatingVideoPlayer : IVideoPlayer
{
ctor(...)
void Play()
{
_internetConnection.Connect();
_loginService.Login();
_decoratee.Play();
}
}
What I dislike with this approach:
Actually the
VideoPlayer
violates the LSP because it does not conform to the interface by not doing all preparation in thePlay()
method, which rather leads me to the facade pattern. Or doesn't it violate the LSP because it will always be decorated by thePreparatingVideoPlayer
when it is injected into the system?What if another client wants to play video without preparation (because the client knows everything is prepared or prepared everything himself)? He wouldn't be able to because letting
IVideoPlayer
be injected will always result in getting thePreparatingVideoPlayer
, which would lead me to the facade pattern again.
Conclusion
So which pattern is more appropriate or are these patterns appropriate at all? Are my concerns valid?
_actualVideoPlayer
implementing a different interface thanIVideoPlayer
whereas_decoratee
is implementingIVideoPlayer
making it the decorator pattern. I am not into giving the construct a name at all costs. But I rather would like to know what pattern is more suitable regarding the intents of the patterns concerning this scenario in contrary to the implementation of the patterns. Additionally are my 'dislikes' to these approaches in this scenario correct?