Search code examples
javadesign-patternsdependency-injectionsolid-principles

Implementing Dependency Injection design pattern


I was told that it's possible to implement the Dependency Injection design pattern two times in the following code and that changing the method signatures was allowed:

public class Person {
    String title;
    ArrayList<String> name = new ArrayList<>();

    public Person() {
        name.add("First");
        name.add("Middle");
        name.add("Last");
    }

    public void setTitle(int i) {
        switch (i) {
            case 0:
                title = "Ms.";
                break;
            case 1:
                title = "Mr.";
                break;
            case 2:
                title = "Mx.";
                break;
    }
    }
}

So my attempt of adding the Dependency Injection is as follows:

public class Person {
    String title;

    ArrayList<String> name = new ArrayList<>();


    public Person(String First,String Middle,String Last) {
        name.add(First);
        name.add(Middle);
        name.add(Last);
    }

    public void setTitle(String title) {

        this.title = title;

    }
}

Is this a correct way of implementing the design pattern? or could this code be implemented in a better way?


Solution

  • The book Dependency Injection Principles, Practices, and Patterns defines Dependency Injection (DI) as

    a set of software design principles and patterns that enables you to develop loosely coupled code. (Chapter 1, page 4)

    An introduction to DI can be found in this excerpt from chapter one of that book, or you can read the full chapter 1 online.

    An important distinction that the book makes is the difference between Stable Dependencies and Volatile Dependencies. DI is concerned about abstracting and injecting Volatile Dependencies, or as the book states:

    Volatile Dependencies are the focal point of DI. It’s for Volatile Dependencies rather than Stable Dependencies that you introduce Seams into your application. Again, this obligates you to compose them using DI.

    From perspective of your Person class, String is a Stable Dependency. Because Dependency Injection is concerned with the injection of Volatile Dependencies, I do not view providing the first name, middle name, and last name values as a form of DI. It would become DI in case the constructor is used to inject a Volatile Dependency, e.g. using an interface. For instance:

    public class UpdatePersonTitleHandler
    {
        private PersonRepository repository;
    
        public UpdatePersonTitleHandler(PersonRepository repository)
        {
            this.repository = repository;
        }
    
        public void handle(UpdatePersonTitle command)
        {
            Person person = this.repository.getById(command.personId);
    
            person.setTitle(command.Title);
    
            this.repository.Update(person);
        }
    }
    

    In this case, the UpdatePersonTitleHandler 'component' depends on the PersonRepository abstraction, which is injected through its constructor (using Constructor Injection). At runtime, the PersonRepository might be implemented by a SqlPersonRepository and the UpdatePersonTitleHandler might be constructed as follows:

    var handler = new UpdatePersonTitleHandler(
        new SqlPersonRepository("connection string")); // <-- constructor injection