Dependency Inversion principle states that instead of instantiating referenced classes within a class, they should be instantiated outside the class definition and passed as references in the class. Dependency Inversion (D in SOLID) injects the reference of the class instance through setter methods of interface or abstract class type. Dependency Inversion relies on abstraction instead of concrete classes. This design principle promotes loose coupling. Since the objects are instantiated outside the class and not within the class this is also called as Inversion of Control.
As Dependency Inversion relies on abstraction, any concrete class instance of the abstract class type can be used. Since the objects are instantiated outside the referenced classes, changes from one object to another of same abstract class type can be done easily without changing the referenced classes. Also, this code change is done at one place instead of making change in every referenced class. This is the advantage of using Dependency Inversion.
The terms Inversion of Control, Dependency Injection, Dependency Inversion mean the same. The term Hollywood principle (don’t call us, we’ll call you) also means the same.
Spring framework provides Dependency Injection.
EJB 3.1 uses both Context and Dependency Injection.
The Factory Method, Template Method, Observer and Chain of Responsibility GOF design patterns follow Dependency Inversion principle.
While designing the implementation of a system you should avoid multiple classes referring to each other. This makes the application difficult to maintain as changes in one part of code could cascade to multiple class changes. Also, unit testing of tightly coupled classes is difficult.
The principle of least knowledge states that a class should only interact with few closely associated classes. It promotes loose coupling and makes the code resilient to changes. It states that only the following methods should be called:
Facade which is a GOF design pattern follows this principle.
Apart from design patterns and design principles, a programming language can have efficient ways of writing code. For example, in the book Effective Java , Joshua Bloch has written about efficient ways of writing a Java code.
GOF design patterns are divided into three categories – Creational, Structural and Behavioral.
The most commonly used GOF Creational design pattern is Factory Method. This design pattern takes the object creation logic outside the client and encapsulates it in a class often called as a Factory. A Factory class provides a static method to create and return objects. The return type of this method is either an abstract class or an interface. Factory Method is used when you do not want to give fine grained control of directly accessing the implementation classes to the client. Factory method decouples the client code from the actual implementation class as it uses abstraction. This design pattern provides Dependency Inversion.
REPORT THIS ADPRIVACY SETTINGS
Factory method can use Singleton design pattern to avoid creation of new objects each time the factory method is called.
DocumentBuilderFactory class of Java is an example of Factory method implementation. Another example of Factory method implementation is the getConnection method of DriverManager class in JDBC. The return type of this method is an interface java.sql.Connection. The actual object returned by this method is of specific driver class type.
Singleton is a GOF creational pattern used to create only one object of a class. The object is created within the class and its constructors are declared private to ensure that the class cannot be instantiated from elsewhere outside the class definition. If a singleton object is being deserialized, then it should return same singleton instance.
With the introduction of enum in Java SE 5, Singleton objects can be declared as enum instead of class.
Enterprise Java Beans (EJB) 3.1 provides Singleton stateless session beans. Spring framework also provides singleton beans.
The use of singleton is discouraged in multithreaded applications as it slows down the performance.
Builder is a GOF creational design pattern. It is used to create a complex object which could consist of any of its components.
StringBuilder class in Java is an example of builder design pattern. A StringBuilder allows creation of a String object which is a combination of multiple strings without creating a new String object for every concatenation.
Another example of Builder implementation – you need to create a SQL query with dynamic Order By clause. There are multiple sorting criteria and the order by should only contain selected criteria. The Builder class in this design has a method buildClause that generates Order By clause based on the selected criteria. All criteria are defined as instance variables in Builder class. If none of the criteria are set the buildClause returns empty string otherwise an Order By clause followed with column names.
Prototype is a creational GOF design pattern used to create multiple complex objects with some initial state. Instead of creating and initializing complex objects every time they are needed, this design pattern allows creating clone of an existing complex object. Nested objects within the cloned object can be shallow or deep cloned.
For example, if you need to create a copy of a complex object then creating a new instance of all related objects and initializing state of each object could become expensive. In a business automation project which allows marketing materials such as documents, questionnaires etc. to be reused, the existing workflow instance can be cloned instead of creating a new workflow.
This creational GOF design pattern provides one layer of abstraction above factory method. The abstract factory is used to decide which factory class should be used to create objects.
Composite design pattern allows defining part-whole hierarchy of objects. If a complex object constitutes of another object of its own type or another object of similar type, it can be defined using composite pattern.
For example, a workflow application allows reviewers to review a project or a program by filling a questionnaire. A program can consist of multiple projects or multiple sub programs. A project is always a part of program. You can design this by creating two classes Project and Program implementing Reviewable interface. The Program class uses a “has a” relationship to declare variable of interface type Reviewable. The instance of Reviewable can either be of class Project or Program. The Questionnaire class also has “has a” relationship of type Reviewable. Due to the interface Reviewable, client class Questionnaire can deal with project and program uniformly.
Composite is based on Single Responsibility design principle.
Adapter design pattern converts interface of a class into the interface that client expects. Adapter classes provide connectivity between the client and classes with incompatible interfaces. The classes with incompatible interfaces are also called as Adaptee classes. Adapter classes either translates a method call from a client into the method calls that the Adaptee class supports. An Adapter can also transform the input or output objects into the object types supported by the Adaptee class.
Adapter classes allow the client code to be decoupled from the Adaptee classes where neither of them knows about the other. The Adapter also helps to handle the changes in the API being called and the client code without changes on either side.