0

This is a common design in the enterprise Java level (though, most of the time references get injected by some frameworks/libraries):

I have an interface

import java.util.*;
public interface ProductRepository {
    public List <Product> getAllProducts();
}

And its implementation

public class ProductRepositoryImp implements ProductRepository {
    private List<Product> products = new ArrayList<Product>();
    public ProductRepositoryImp() {
        products.add(new Product("Blackberry", 24000));
        products.add(new Product("Nokia", 45000));
        products.add(new Product("Samsung", 91000));
    }
    @Override
    public List<Product> getAllProducts() {
        return this.products;
    }
    public int localMethod(){
        return 2;
    }

}

In the main class (controller) I reference the interface (ProductRepository) instead of the implementation (ProductRepositoryImp)

public class ProductController {
    static ProductRepository productRepository;
    public static void main(String[] args) {
        productRepository = new ProductRepositoryImp();

        for (Product p : productRepository.getAllProducts()) {
            System.out.println(p.getName());
            System.out.println(p.getPrice());
            System.out.println("");
        } } }

Why?

Here is an explanation I read in a book:

It is not the best practice to connect two layers (controller and persistence) with a direct reference. Instead, we can, in future, have an interface reference in the controller so that we can easily switch to different implementations of the repository without doing any code changes in the controller class.

What's the benefit of accessing .getAllProducts() from the ProductRepository instance instead of an instance of ProductRepositoryImp?

What's the point of "without doing any code changes" switching in the quote above? I know it's something related if we have lets say "AnotherProductRepositoryImp"?.

What if I want to heavily access some .localMethod() instead which is inside the ProductRepositoryImp instance ?

Kedar Mhaswade
  • 4,535
  • 2
  • 25
  • 34
  • While http://stackoverflow.com/questions/2586389/when-should-i-use-an-interface-in-java is related, its answers are quite dated, and most of its answers to do not apply to the present question. – meriton Mar 05 '17 at 14:01
  • @Hey-men-whatsup Could you share the title of the book you got the explanation from? – lukeg Mar 05 '17 at 14:42
  • @lukeg, I think you could find it easily, I mean, it's kinna,, prohibited to me to mentioned it directly :D – Plain_Dude_Sleeping_Alone Mar 05 '17 at 15:35
  • Interfaces define type, classes define implementation. Type-oriented programming is extremely powerful, flexible, and scalable. It makes code easier to read and maintain. It helps prevent bugs. See Joshua Bloch's _Effective Java_, items 18, 19, and 52 (2nd ed.) – Lew Bloch Mar 05 '17 at 18:54

2 Answers2

2

What's the benefit of accessing .getAllProducts() from the ProductRepository instance instead of an instance of ProductRepositoryImp?

ProductRepository is your interface to your data layer. It is totally agnostic of the underlying database.

what's the point of "without doing any code changes" switching in the quote above? I know it's something related if we have lets say "AnotherProductRepositoryImp"?.

In this case it is not related to AnotherProductRepositoryImp, but lets say the underlying database changes. Each database has different query formats and the corresponding implementation of the query goes in ProductRepositoryImpl class. The changes would not be AnotherProductRepositoryImp but ProductMongoRepositoryImp, ProductMySqlRepositoryImp, ProductFileRepositoryImp etc

If you are coding to interfaces, then you will not have to make any changes to your controller. Just inject another implementation and you are done.

What if I want to heavly access some .localMethod() instead which is inside the ProductRepositoryImp instance ?

If you are using any method which is not a part of interface and being used only internally in your implementation, then it is not a part of contract with the interface and need not be exposed to the outside world(i.e declare it private). If it is to be exposed to the outside world, it means it is outside the contract with the interface. You would typically need to typecast to the correct instance type to access that value.

meriton
  • 68,356
  • 14
  • 108
  • 175
Rahul
  • 15,979
  • 4
  • 42
  • 63
2

The benefit is that you can inject another implementation into your controller, such as a mock repository for testing, or a repository for a different SQL dialect.

Separating interfaces from implementations can also be used to make it explicit which methods are intended to be used by callers (cf. information hiding, encapsulation), though this can also be accomplished by access modifiers (such as private). The important thing is that the team agrees on which signaling mechanism they use to avoid misunderstandings.

While the use of interfaces was mandated by many early enterprise frameworks, most notably EJB until version 3.1, modern frameworks no longer enforce that.

Today, it is somewhat debated whether interfaces with only one implementation should exist. Some say yes for consistency, some say no for simplicity.

meriton
  • 68,356
  • 14
  • 108
  • 175
  • Accidentally tough, this mornings I encoutered discussion where a group rejecting the use of the *polymorphism* style of an interface, where they emphasized to the thing you've said exactly, simplicity. +1 – Plain_Dude_Sleeping_Alone Mar 05 '17 at 15:30