Dependency Inversion Principle (DIP for short) states:
One should depend upon abstractions and their concrete implementation.
The advantage of Dependency Inversion is that the classes do not need to know about the concrete implementation, just its abstraction.
public class UserFileRepository
{
void SaveUser(User user);
}
public class UserService
{
public void CreateUser(User user)
{
UserFileRepository repository = new UserFileRepository();
repository.SaveUser(user);
}
}
The code above is totally fine, but it does not respect the Dependency Inversion Principle. The User class know about the concrete implementation of the UserFileRepository
, making it too dependent, if anything needs to be changed in UserFileRepository
, the UserService
class will need to be changed.
We can solve this issue by changing the concrete reference to an interface
.
public interface IUserRepository
{
void SaveUser(User user);
}
public class UserFileRepository : IUserRepository
{
public void SaveUser(User user)
{
// Saves User to a file
}
}
public class UserService
{
private readonly IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public void CreateUser(User user)
{
_userRepository.SaveUser(user);
}
}
void Main()
{
IUserRepository repository = new UserFileRepository();
UserService userService = new UserService(repository);
User newUser = new User();
userService.CreateUser(newUser);
}
Now the UserService
is not dependent on the concrete implementation of UserDBRepository
but on its contract IUserRepository
.
If the application needs to change from saving to a file and save it to a database, we can simply create another concrete implementation of the IUserRepository
and pass it as an argument to the UserService
.
public interface IUserRepository
{
void SaveUser(User user);
}
public class UserFileRepository : IUserRepository
{
public void SaveUser(User user)
{
// Saves User to a file
}
}
public class UserDBRepository : IUserRepository
{
public void SaveUser(User user)
{
// Saves User to a database
}
}
public class UserService
{
private readonly IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public void CreateUser(User user)
{
_userRepository.SaveUser(user);
}
}
void Main()
{
// Changed from File to DB repository
IUserRepository repository = new UserDBRepository();
UserService userService = new UserService(repository);
User newUser = new User();
userService.CreateUser(newUser);
}
In this example, this code can be changed even further, changing the UserService
to have its interface and implement it.
Top comments (0)