Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SOLID Design Principles : Liskov Substitution Principle and Dependency Inversion Principle

Just a thought and a question to the Stack Overflow and Microsoft Development Community about the OO software design principles called SOLID. What is the difference between the Liskov Substitution Principle and the Dependency Inversion Principle please ? I have thought about this for a while and I'm not sure of the difference. Please could you let me know ? Any thoughts / feedback very welcome.

like image 328
TaherHassan Avatar asked Dec 31 '22 14:12

TaherHassan


1 Answers

Liskov's substitution Principle states the following:

A class should be directly substitutable with its base-class

What this means is that if a child class extends a parent class, it should be directly substitutable. Image viewable here

If you take Bird for example. Not all birds fly - but some do.

Lets look at a java example:

Bird  ostrich = new Ostrich();

If I am going to treat my ostrich as a Bird (is base/parent class), and we have functionality in Bird for that ostrich to fly, even though they shouldn't!

So we can separate out the structure: Refactored hierarchy for Liskov's

Dependency Inversion is easier when thought of as a separate principle.

If we have a class call a class. It makes it very hard to change it later and it is going to need us to change source code. Again lets look at a code example.

public class App {
    public static void main(String[] args) {
        Greeting greeting = new Greeting();
        greeting.sayHello(new Friend()); 
        greeting.sayHello(new Enemy());
    }
}

public class Greeting {
    public void sayHello(Person person) {
         person.greet();
    }
}

public interface Person {
    public void greet();
}

public class Friend implements Person {
    public void greet() {
        System.out.println("Hello my friend");
    }
}

public class Enemy implements Person {
    public void greet() {
        System.out.println("Go away");
    }
}

Here we pass a parent object (Person) of both of items (Friend and Enemy). If we passed through a Friend object, we would need a separate identical method for the Enemy method. We can use the Open/Closed principle to have a single method which can call either Friend or Enemy or anything in the future which might extend Person. Dependency inversion is that rather than the sayHello() method creating a class, the Parent object is passed through. This means that which Parent object we call is dependent on App, rather than sayHello() determining which object to call.

It is better practice to use dependency inversion. The class greet() calls is not set in stone, as long as the class being passed is that which implements Person.

What this means is that instead of App being dependent on Friend. Whether Friend or Enemy gets called is dependent on App.

Passing responsibility up like this means that our code can be easily maintained and changed. Using Context and Dependency Injection, it is possible for configuration files to determine which type of object we want to use when a specified interface is referenced.

like image 83
christophperrins Avatar answered Jan 03 '23 03:01

christophperrins