The objective is to develop a client for voice over IP service which is able to handle calling and receiving calls. In order to reduce the complexity of the example this article will not go in depth about the peer to peer connection of the application.
As it can be seen above, the functionality is pretty straight forward but there are a lot of possibilities which will be requested in the future like handling the “No Answer”, “Busy”, “Call Waiting” and so on, therefore the logic should be designed the way that any kind of new feature can be added smoothly and with lowest impact on the main logic.
In computing and systems design a loosely coupled system is one in which each of its components has, or makes use of, little or no knowledge of the definitions of other separate components. Subareas include the coupling of classes, interfaces, data, and services. Loose coupling is the opposite of tight coupling.
In object-oriented programming, the open/closed principle states " software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification"; that is, such an entity can allow its behaviour to be extended without modifying its source code.
The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
Developers often use the facade design pattern when a system is very complex or difficult to understand because the system has a large number of interdependent classes or because its source code is unavailable. This pattern hides the complexities of the larger system and provides a simpler interface to the client.
As it can be seen in the diagram above by the use of facade pattern we have accomplished a simple gateway(Manager class) to our logic and the observer pattern(Event Handler) will take care of the loosely coupled relationship between CallHandler and DeviceHandler classes.
The EventHandler class is just a blue print which will be implemented in the Manager class and will be passed to the DeviceHandler and CallHandler so any changes which will be applied to either DeviceHander or CallHandler classes will not effect each other directly, instead both CallHandler and DeviceHandler classes have the choice to consume the events which have been fired in any of them without being dependent on each other directly therefore the developer can change then individually .
This combination of the design patterns has been extremely helpful in my projects and I hope you can benefit form it as well :)