Question

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 to CreateEngine(), CreateCarBody() and so on.
  • I face a naming issue because the interface the type of _actualVideoPlayer implements could also be named IVideoPlayer, 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 the Play() method, which rather leads me to the facade pattern. Or doesn't it violate the LSP because it will always be decorated by the PreparatingVideoPlayer 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 the PreparatingVideoPlayer, 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?

Was it helpful?

Solution

Decorator pattern

Let's start off nice: I hate your second solution.

IVideoPlayer is an interface; a "contract" that any implementing class does a certain thing. It's a contract on the code side (between caller and implementation), but in a way it's also interpersonal between the programmers working with it - the compiler won't stop me if I implement IVideoPlayer with Play() erasing the hard drive.

The 2 implementations are not fulfilling the same contract, they just have a method with the same name.

The safety an interface is supposed to provide is not given here. Even worse, because of this expectation of such a contract, it makes it more likely that somebody will get it wrong.

Naming things

There are 2 hard thing in computer science, one of them is naming things. Don't underestimate it, a thesaurus is one of the most undervalued programming tools. You should have 2 different names that convey the difference between the 2 implementations.

To give examples, you could rename the "outer" one to VideoSystem: one is the whole system, while the other one is only the player. Or you could rename the inner one VideoRenderer: one is the whole player, while the other is only the part "rendering" the video.

As the outer one seems to be an exposed API, I would rather go with renaming the inner one, because you can easier explain the inner one to your coworkers than the outer one to your clients.

Patterns

Wikipedia says about the Decorator Pattern

What problems can the Decorator design pattern solve?

  • Responsibilities should be added to (and removed from) an object dynamically at run-time.
  • A flexible alternative to subclassing for extending functionality should be provided.

About the Facade Pattern, Wikipedia says

What problems can the Facade design pattern solve?

  • To make a complex subsystem easier to use, a simple interface should be provided for a set of interfaces in the subsystem.
  • The dependencies on a subsystem should be minimized.

Neither of those is your goal here.

You're not working on this because you want to add or remove things dynamically at run-time, or want to extend functionality, or because your subsystem is too difficult to use, or you have too many dependencies on a subsystem.

You are trying to create some functionality in the first place.

Solution

Don't think "which pattern should I apply". Do what works. In the end your code might turn out to be an already established pattern and then when your coworkers ask about the code you can tell them "I solved it with {pattern name}". That's about all the advantage you get from using a pattern.

All that being said, do the first thing.

However, calling that a facade might be confusing, because a lot of people see facades as rather simple classes, just "passing along" methods (e.g. if you also had a method Connect() calling _internetConnection.Connect();). Examples on Wikipedia say otherwise, but they don't seem to be particularly good (e.g. repeatedly calling new in constructors).

You have a VideoPlayer class, and to do its job, it needs other classes - I'd just call that good old composition. Nobody will misunderstand you if you call it composition.

Licensed under: CC-BY-SA with attribution
scroll top