1

In Head First Design Patterns, it was mentioned that you should code to an interface instead of an implementation however the last part of the code example got me confused. How is assigning the concrete implementation of an object at runtime a better design?

Does it mean that its better to put the instantation of the objects within a method in the class that uses the supertype? (a method whose purpose is specifically returning an object to a variable of the superclass)

//Programming to an implementation would be:
Dog d = new Dog();
d.bark();

//Programming to an interface/supertype would be:
Animal animal = new Dog();
animal.makeSound();

//Even better is assigning the concrete implementation at runtime: (says the book)
a = getAnimal();
animal.makeSound();
3

2 Answers 2

1

Even better way is to get the concrete class figured by someone else depending on the environment/context of your code execution. This is called Inversion of control/ dependency injection where the actual class is either configured in some configuration files or coding by convention is used to identify the correct file.

Coming back to why,imagine a project of moderate complexity where you have to talk to a DB. If you hard code the way to access a DB , you will end up asking customers to stick to a particular type/version of the DB. This is how JDBC works. Similarly for more complex scenarios, imagine moving from Db based system file based. Once you get that software should be designed for flexibility, its easy to appreciate the delayed initialisation of concrete classes.

Sign up to request clarification or add additional context in comments.

3 Comments

Hello, I had the same question hoping you could please clarify with one concrete example, more specifically how would one implement the function getAnimal in the a = getAnimal(); a.makeSound()? How would one invoke getAnimal (Without an object nor a Static class)? Would this function contain a constructor of a class?
With this approach, you can completely remove the dependency of Animal from A. As such , your code can live in different repos and completely different teams can work on module A( loosely used instead of project/jar) and module Animal without knowing even knowing Animal will be used at runtime. You can then create third module with class DifferentAnimal and use it to inject instead of Animal.
wow! Stackoverflow commenting is so bad. Here is code sample using Spring framework. Beauty is that you don't need to worry about getAnimal() method - that is now the job of the Dependency Injection framework. Spring and Guice are two biggest DI frameworks in Java class A { @Autowired private BeingAnimal a; public void someMethod() { a.makeSound(); } } class Animal implements BeingAnimal { public void makeSound() { } }
0

If I were to say why in one word, then it would be: Centralization.

What I mean by this, is that you assign those concrete types at the start of your application somewhere in a single place and provide them to the classes that need them as interfaces, so those classes don't get coupled to the concrete types themselves but rather rely on those abstractions or interfaces.

This is similar to using the Factory pattern, so you don't spread object creation through out the program but rather in a single spot, which is easy to modify in the future.

This also enables you to use Dependency Injection and Inversion of Control which in turn comes with a bunch of good stuff like better testing, maintainability, run-time configuration, etc .

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.