Code/Program for Interface not for Implementation Explained

In this article, we will discuss code for Interface, not for implementation best practice with an example.
Check out Java best practices series at https://www.javaguides.net/p/java-best-practices.html
Always program for the interface and not for application; this will lead to flexible code that can work with any new implementation of the interface.
So use interface type on variables, return types of method or argument type of methods in Java.
This has been advised in many Java books, including in Effective Java and Head First design pattern book.
Let's understand this best practice with Java example.

Video

The code for Interface, not for implementation best practice very well explained in the below video tutorial:

Code/Program for Interface not for Implementation

Let's create Shape interface with its multiple implementations such as ass Circle, Rectangle, Square:
interface Shape {
    void draw();
}

class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println(" drawing circle ....");
    }
}

class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println(" drawing rectangle ....");
    }
}

class Square implements Shape {
    @Override
    public void draw() {
        System.out.println(" drawing square ....");
    }
}

Look at here, we are using an interface as refer type and method argument:
public class Test {

    public static void main(String[] args) {
        Shape shape = new Circle();
        print(shape);
    }

    private static void print(Shape shape) {
        shape.draw();
    }
}
Output:
 drawing circle ....
With code for interface, not for implementation technique, you can change the implementation any time without changing the existing code. For example, we can change from Circle to Square:
Shape shape = new Square();
Let's understand this approach with a collections framework.

Code for Interface, not for Implementation in Collections Framework

1. Always use interface type as a reference type.

For example, use ListSetMap, etc interfaces as a reference type.
// Better
List<String> list = new ArrayList<>(); 

// Avoid
ArrayList<String> list = new ArrayList<>();

// Better
Set<String> set = new HashSet<>();

//Avoid
HashSet<String> employees = new HashSet<>();

// Better
Map<String,String> map = new HashMap<>();

//Avoid
HashMap<String,String> map = new HashMap<>();
By declaring a collection using an interface type, the code would be more flexible as you can change the concrete implementation easily when needed, for example:
List<String> list = new LinkedList<>(); 
When your code is designed to depend on the List interface, then you can swap among List’s implementations with ease, without modifying the code that uses it.

2. Always use interface type as a return type

For example,
public Collection listEmployees() {
    List<Employee> employees = new ArrayList<>();
    // add Employees to the list
    return employees;
}

3. Always use Interface Types as a method argument

public void foo(Set<Integer> numbers) {
}
The flexibility of using interface type for a collection is more visible in the case of the method’s parameters.
Check out Java best practices series at https://www.javaguides.net/p/java-best-practices.html

Java Best Practices

Comments