28

Over the last few months, I stumbled a few times over the following technique / pattern. However, I can't seem to find a specific name, nor am I a 100% sure about all its advantages and disadvantages.

The pattern goes as follows:

Within a Java interface, a set of common methods is defined as usual. However, using an inner class, a default instance is leaked through the interface.

public interface Vehicle {
    public void accelerate();
    public void decelerate();

    public static class Default {
         public static Vehicle getInstance() {
             return new Car(); // or use Spring to retrieve an instance
         }
    }
 }

For me, it seems that the biggest advantage lies in the fact that a developer only needs to know about the interface and not its implementations, e.g. in case he quickly wants to create an instance.

 Vehicle someVehicle = Vehicle.Default.getInstance();
 someVehicle.accelerate();

Furthermore, I have seen this technique being used together with Spring in order to dynamically provide instances depending on the configuration. In this regard, it also looks like this can help with modularization.

Nevertheless, I can't shake the feeling that this is a misuse of the interface since it couples the interface with one of its implementations. (Dependency inversion principle etc..) Could anybody please explain to me how this technique is called, as well as its advantages & disadvantages?

Update:

After some time for consideration, I rechecked and noticed that the following singleton version of the pattern was used far more often. In this version, a public static instance is exposed through the interface which is initialized only once (due to the field being final). In addition, the instance is almost always retrieved using Spring or a generic factory which decouples the interface from the implementation.

public interface Vehicle {
      public void accelerate();
      public void decelerate();

      public static class Default {
           public static final Vehicle INSTANCE = getInstance();

           private static Vehicle getInstance() {
                return new Car(); // or use Spring/factory here
           }
      }
 }

 // Which allows to retrieve a singleton instance using...
 Vehicle someVehicle = Vehicle.Default.INSTANCE;

In a nutshell: it seems that this is a custom singleton/factory pattern, which basically allows to expose an instance or a singleton through its interface. With respect to the disadvantages, a few have been named in the answers & comments below. So far, the advantage seems to lie in its convenience.

Jérôme
  • 669
  • 6
  • 11
  • some kind of singleton pattern? – Bryan Chen Dec 16 '13 at 05:04
  • I think you're right that the interface shouldn't "know" about its implementations. Probably `Vehicle.Default` should be moved up into the package namespace as a factory class, e.g. `VehicleFactory`. – augurar Dec 16 '13 at 06:43
  • 7
    By the way, `Vehicle.Default.getInstance() != Vehicle.Default.getInstance()` – Konrad Morawski Dec 16 '13 at 08:13
  • 20
    The antipattern here is to use the car-analogy antipattern, closely related to the animal-analogy antipattern. Most software doesn't have wheels or legs. – Pieter B Dec 16 '13 at 08:32
  • @PieterB: :-)))) You made my day! – Doc Brown Dec 16 '13 at 10:57
  • I’m aware of the car-analogy anti-pattern and I even considered using another example for exactly this reason.. :) Fact is however, that I have seen this technique being used throughout a large code-base where the interfaces were used to group various implementations of business related functionality. However, if I remember correctly, the technique was most often used in combination with Spring in order to dynamically inject a default implementation defined by a configuration file. – Jérôme Dec 16 '13 at 22:02
  • I am aware that this may not be considered an exact answer but since I cannot comment this a way to contribute. The answer to this question http://stackoverflow.com/q/3427073/3110605 pretty much looks like the construct described in the question and the feedback may offer some insights. – real_paul Dec 17 '13 at 10:14
  • @augurar: Why shouldn't an interface know about its implementations, if it spares clients from having to do so? If the purpose of having something be an interface is to allow instances of classes whose primary purpose is to do something else also be usable by code which wants the interface, why shouldn't code that simply wants something that implements the interface, be able to ask for something that simply implements the interface? – supercat Mar 14 '14 at 22:17
  • @PieterB most software doesn't have... well, anything! –  Feb 28 '18 at 18:42

2 Answers2

24

Default.getInstance is IMHO just a very specific form of a factory method, mixed up with a naming convention taken from the singleton pattern (but without being an implementation of the latter). In the current form this is a violation of the "single responsibility principle", because the interface (which already serves the purpose of declaring a class API) takes the additional responsibility of providing a default instance, which would be much better placed in a separate VehicleFactory class.

The main problem caused by this construct is that it induces a cyclic dependency between Vehicle and Car. For example, in the current form it won't be possible to place Vehicle in one library, and Car in another. Using a separate factory class and placing the Default.getInstance method there would solve that problem. It may be also a good idea to give that method a different name, to prevent any confusion related to singletons. So the result could be something like

VehicleFactory.createDefaultInstance()

Doc Brown
  • 199,015
  • 33
  • 367
  • 565
  • Thanks for your answer! I agree that this particular example is a violation of the SRP. However, I'm unsure whether it is still a violation in case the implementation is dynamically retrieved. E.g. by using Spring _(or a similar framework)_ in order to retrieve a particular instance defined by for example a configuration file. – Jérôme Dec 16 '13 at 22:07
  • 1
    @Jérôme: IMHO a non-nested class named `VehicleFactory` is more conventional than the nested construct `Vehicle.Default`, especially with the misleading "getInstance" method. Though its possible to circumvent the cyclic dependency by using Spring, I would personally prefer the first variant just because of common sense. And, still it leaves you with the option of moving the factory to a different component, changing the implementation afterwards to work without Spring etc. – Doc Brown Dec 17 '13 at 08:54
  • Oftentimes, the reason for using an interface rather than a class is to allow classes which have other purposes to be usable by code which needs an interface implementation. If a default implementing class can meet all of the needs of code which simply needs something that implements the interface in "normal" fashion, specifying a means of creating an instance would seem a useful thing for the interface to do. – supercat Feb 24 '14 at 02:33
  • If Car is a very generic, standard implementation of Vehicle, this is not a violation of SRP. Vehicle still has only a single reason to change, e.g. when Google adds an `autodrive()` method. Your very generic Car must then change to implement that method, e.g. by throwing an NotImplementedException, but that _does not confer an additional reason_ to change on Vehicle. – user949300 Oct 02 '14 at 20:51
  • @user949300: the SRP is not a "mathematical provable" concept. And software design decisions are not always "black-and-white". The original code is not so bad it could not be used in production code, of course, and there may be cases where the convenience outweighs the cyclic dependency, as the OP has noted by himself in his "update". So please read my answer as "consider if using a separate factory class does not serve you better". Note also the author changed his original question a bit after I gave my answer. – Doc Brown Oct 03 '14 at 05:11
  • Agree with your second sentence. Not sure if some CS PhD has tried proofs of SRP. And agree that the cyclic dependency could be problematical. However, when you cite SRP as a reason to prefer one design over another, you should cite SRP correctly. Its unfortunate that SRP is poorly named, as the "responsibility" part is often misunderstood. – user949300 Oct 03 '14 at 06:20
  • @user949300: SRP was not "invented" by Bob Martin, and his definition is not the one-and-only correct one. Maybe he introduced this term first, but the principle itself is older than the term. – Doc Brown Oct 03 '14 at 06:41
  • The link you cite for SRP in _your own answer_ supports my comments. Find another to support your version of SRP. :-) – user949300 Oct 03 '14 at 06:55
  • @user949300: you believe it supports your comments since you are biased. Actually, Wikipedia says Bob Martin invented *the term* (as I wrote above), not "his definition of classes having single responsibilities is the one-and-only correct one". – Doc Brown Oct 04 '14 at 08:31
  • Of course I'm biased. You are not? At least I present supporting docs. Read the link you cited, whose plain text supports my position. Now, Wikipedia isn't perfect, so if you don't like that definition of SRP, find another one and link to it. But don't cite a link saying "single reason to change" and call me biased for _quoting your link_! – user949300 Oct 05 '14 at 01:48
3

This looks like Null Object pattern to me.

But that heavily depends on how Car class is implemented. If it is implemented in "neutral" way, then it is definitely a Null Object. That means, if you can remove all null checks on the interface and put instance of this class instead of each occurrence of null, then code still has to work correctly.

Also if it is this pattern, then there is no problem of creating tight coupling between the interface itself and implementation of null object. Because null object can to be everywhere where said interface is used.

Euphoric
  • 36,735
  • 6
  • 78
  • 110
  • 2
    Hello and thanks for the answer. Although I'm pretty sure that in my case this wasn't used to implement the "Null Object" pattern, it is an interesting explanation. – Jérôme Dec 16 '13 at 22:11