SOLID Design Principles – Part 5

SOLID Design principles

In this series we are looking at the SOLID design principles. In this post, we’ll cover the last principle in the acronym: the Dependency Inversion principle (DIP).

If you missed the previous posts in this sequence, you can find them here:

The Dependency Inversion Principle

The principle is usually stated as follows:

“Details should depend upon abstractions. Abstractions should not depend upon details”.

Robert C. Martin’s definition of the Dependency Inversion principle consists of two parts:

  • High-level modules should not depend on low-level modules. Both should depend on abstractions.
  • Abstractions should not depend on details. Details should depend on abstractions.

The idea behind this principle is very simple: high-level modules (which provide complex logic) should be easily reusable without being affected by changes in low-level modules (which provide utility features).

To achieve this, we introduce an additional abstraction (usually a well-defined interface) that decouples the high-level and low-level modules from each other. Both the high-level and the low-level modules depend on this interface. We end up with two dependencies:

  • the high-level module depends on the abstraction (interface), and
  • the low-level modules depend on the same abstraction (interface).

This interface abstraction removes the dependencies between the higher-level and lower-level software components.

This sounds more complex than it actually is. If we consistently apply both the Liskov Substitution principle and the Open-Closed principle to our code, we will automatically follow the Dependency Inversion principle. The Open-Closed principle says that a software component should be open for extension, but closed for modification. We can easily do this by introducing a high level interface (which is itself closed for modification). We can then create different class implementations of that interface. If our classes follow the Liskov Substitution principle, then we can replace them with other implementations of the same interface without breaking our application.


XStream is a simple, easy to use Java library for serializing Java objects to XML or JSON and vice versa.

XStream uses the Dependency Inversion principle by creating a HierarchicalStreamDriver interface that provides a high level abstraction to model a stream reader and writer. XStream provides a number of concrete driver classes. Each concrete driver class implements this HierarchicalStreamDriver interface. The interface decouples the main XStream class from the actual driver class being used to read and write the stream.

Both the high-level module (the XStream class) and the low-level modules (the concrete driver classes) depend on the same abstraction (the HierarchicalStreamDriver interface). They can be changed independently of each other without breaking the application, as long as they conform to the same interface.

Here’s a simple example serializing a Person class to both XML and JSON. The XStream class has a toXML() method that serializes a Java object to XML. Depending on the driver used, the toXML() method will either serialize to XML or to JSON.

import com.thoughtworks.xstream.XStream;

// DomDriver reads from *and* writes to XML

// JettisonMappedXmlDriver.class writes to *and* reads from JSON

// JsonHierarchicalStreamDriver *only* serializes/writes to JSON

import java.util.*;

public class XStreamTest {

    public static void main (String args[]) throws IOException {

        // the heart of it...
        XStream xstream;

        // create an Address object
        Address address = new Address("42", "Yellow Brick road", "Emerald City", "Land of Oz");

        // create a Person object
        Person p1 = new Person("Dorothy Gale", 17, Gender.FEMALE, address);

        // writing to XML
        xstream = new XStream(new DomDriver());
        String xml = xstream.toXML(p1);
        System.out.println("\nUsing the DomDriver:\n" + xml);

        // writing to JSON
        xstream = new XStream(new JettisonMappedXmlDriver());
        String json1 = xstream.toXML(p1);
        System.out.println("\nUsing the JettisonMappedXmlDriver:\n" + json1);

        // writing to JSON
        xstream = new XStream(new JsonHierarchicalStreamDriver());
        String json2 = xstream.toXML(p1);
        System.out.println("\nUsing the JsonHierarchicalStreamDriver:\n" + json2);

        // deserializing from XML; also works from JSON
        Person p2 = (Person) xstream.fromXML(xml);
        System.out.println("\ntoString():\n" + p2);
} // end of class

This is a great illustration of both the Dependency Inversion principle and the Liskov Substitution principle at work!

This is the end of the series on the SOLID design principle. Tune in next week, same time, same channel, for more exciting Java tips!

As always, please share your comments and questions. If you missed it, you can find the previous articles in this series on the blog as well.

Leave a Comment

Your email address will not be published. Required fields are marked *

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.