Code for Interface, Not for Implementation Best Practice

📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.

🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.

▶️ Subscribe to My YouTube Channel (176K+ subscribers): Java Guides on YouTube

▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube

In this article, we will discuss the best practice of coding to an interface, not to an implementation, with an example. Always program to an interface, not an implementation; this leads to flexible code that can work with any new implementation of the interface. This principle is advised in many Java books, including "Effective Java" and "Head First Design Patterns".

Check out the Java Best Practices series at Java Best Practices.

Video

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

Code: Program for Interface, Not for Implementation

Let's create a Shape interface with multiple implementations, such as Circle, Rectangle, and 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 ...");
    }
}

Here, we use the interface as the reference 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 the "code for interface, not for implementation" technique, you can change the implementation anytime without changing the existing code. For example, we can change from Circle to Square:

Shape shape = new Square();

Code for Interface, Not for Implementation in Collections Framework

1. Always use interface type as a reference type.

Example:

// 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 is 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, you can swap among List’s implementations with ease without modifying the code that uses it.

2. Always use the interface type as a return type.

Example:

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

3. Always use Interface Types as a method argument.

Example:

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.

Conclusion

Coding to an interface, not an implementation, is a crucial best practice in Java that promotes flexibility and maintainability in your codebase. This approach ensures that your code can easily adapt to new implementations without significant changes.

Check out more Java best practices series at Java Best Practices.

Java Best Practices

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare