Low coupling principle aims to reduce the dependency within a software system. Minimise the impact of changing to one component which affects the rest of the system.
Consider this library system example, the system has several main functionalities:
Manage books
Lending books to members
Sending notifications to members
Book
Member
Email service
SMS service
Lending manager
Client
Design issue
Observe the diagram, the LendingManger class is directly dependent on EmailNotificationService and SMSNotificiationService.
This creates tightly coupled system. When there are changes to the notification services or new a notification service is added to the system, the LendingManager has to make changes to incorporate new responsibilities.
Low coupling design
To reduce the coupling and avoid direct dependency, we can create an interface for notifications.
We retain original design for Book and Member, meanwhile we create an NotificationService interface that defines a sendNotification() method.
Notification service interface
Concrete notification services
We now arrange EmailNotificationService and SMSNotificationService to implement the interface.
Modified lending manager
We modify the LedingManger to not create dependency on the concrete notification services. It uses the NotificationService interface to dynamically accept notification type from the client.
Modified client
After the redesign, the LendingManager no longer dependent on the notification services. We can easily extend new notification services or modify notification services behaviour without making changes to the LendingManager class.
The high-level component is not directly depending on concrete notifications, but rather depend on an abstraction, which reduces the system coupling.