DIP says that the most stable systems are those in which source code dependencies refer to abstractions and not to concretions.
Dependency inversion principle cannot be followed as rule because in reality we have to depend on concrete implementations like operating systems, platforms, String in Java, etc. The dependencies like these which are stable and very unlikely to change are excluded from this principle.
The dependencies that are volatile, that are still developing, that can change, we should be depending on their interfaces and not on concrete implementations.
Stable Abstractions
Stable architectures are those that avoid depending on volatile concretions and that favor the use of stable abstract interfaces. They follow following rules –
Don’t refer to volatile concrete classes
Don’t derive from volatile concrete classes
Don’t override concrete functions – concrete functions have dependencies, when you override them, you inherit these dependencies. So ideally we should make functions abstract and create multiple functions.
Never mention the name of anything concrete and volatile
Thanks for stopping by! I hope this gives a good preview into DIP. Eager to hear your thoughts and chat, please leave comments below and we can discuss.
In the last two posts on Factory Pattern using Factory method – part 1 and part 2, we went through how factory method works, using the toyota car factory example. Let’s continue to build on that example and understand the Abstract Factory Pattern.
Using the factory method, we implemented our interfaces CarFactory and ToyotaCar and their concrete implementations for Toyota. But the toyota leaders found out that their factories in California and Washington are not using the genuine toyota parts while assembling Toyota cars, thereby degrading quality of the cars. And so toyota has decided to create a factory for genuine toyota parts that produces these parts and sends them to the car factories.
Let’s call the parts factory ToyotaPartsFactory. CaliforniaToyotaPartsFactory and WashingtonToyotaPartsFactory will now supply these parts to the CaliforniaToyotaCarFactory and WashingtonToyotaCarFactory respectively
public interface ToyotaPartsFactory {
public Engine createEngine();
public Wheels wheels();
public Seats seats();
}
public class CaliforniaToyotaPartsFactory implements ToyotaPartsFactory {
public Engine createEngine() {
return V8Engine();
}
public Wheels createWheels() {
return AlloyWheels();
}
public Seats createSeats() {
return LeatherSeats()l
}
}
Our new ToyotaCar object would now have an abstract method called assembleParts. This would be implemented by the subclasses to use the correct parts while assembling the car. In our concrete CarFactories, we will now be passing the respective ToyotaPartFactories. As shown below, in the CaliforniaToyotaPartsFactory we are passing the CaliforniaToyotaPartsFactory.
public abstract class ToyotaCar {
String modelName;
Engine engine;
Wheels wheels;
Seats seats;
abstract void assembleParts();
void polish() {
System.out.println("Polishing "+modelName+" car";
}
}
public class Sienna extends ToyotaCar {
ToyotaPartsFactory toyotaPartsFactory;
public Sienna(ToyotaPartsFactory toyotaPartsFactory) {
this.toyotaPartsFactory = toyotaPartsFactory;
}
void assembleParts() {
System.out.println("Assembling "+modelName+" car";
engine = toyotaPartsFactory.createEngine();
wheels = toyotaPartsFactory.createWheels();
seats = toyotaPartsFactory.createSeats();
}
}
public class CaliforniaToyotaCarFactory extends CarFactory {
ToyotaCar createCar(String model) {
ToyotaCar car = null
ToyotaPartsFactory toyotaPartsFactory = new CaliforniaToyotaPartsFactory();
if(model.equals("sienna") {
return new Sienna(toyotaPartsFactory);
} else if(model.equals("highlander") {
return new HighLander(toyotaPartsFactory);
} else if(model.equals("prius") {
return new Prius(toyotaPartsFactory);
else {
return null;
}
}
}
We now have the power to create a family of different part objects. That’s what an Abstract Factory does. It gives an interface for creating a factory of products. The second advantage is decoupling. Our code for creating products (ToyotaCar) is decoupled from the code for creating the other line of product families. It opens up the architecture for creating different types of factories needed, with each decoupled from others.
Thanks for stopping by! Hope this gives you a perspective on Abstract Factory pattern. Post comments to start a discussion. See you in the next post.