Design Patterns?-?[3] Behavioral
Design Patterns?-?Behavioral

Design Patterns?-?[3] Behavioral

In the previous article [2] Structural Design Patterns, we discussed in details the some of the most famous example of the Structural Design Patterns. Now we will continue with our next design pattern.

[3] Behavioral Design Patterns

Behavioral design patterns are design patterns that focus on communication between objects, defining a way for objects to interact and collaborate with each other to accomplish a common goal. These patterns are concerned with the flow of control between objects and how they interact to produce a desired outcome.

[1] Chain of Responsibility, Command, Mediator, and Observer, address various ways of connecting senders and receivers of requests:

  • Chain of Responsibility passes a request sequentially along a dynamic chain of potential receivers until one of them handles it.
  • Command establishes unidirectional connections between senders and receivers of requests.
  • Mediator eliminates direct connections between senders and receivers, forcing them to communicate indirectly via a mediator object.
  • Observer lets receivers dynamically subscribe to and unsubscribe from receiving requests.

[2] Strategy lets the class vary its behavior when its strategy gets changed at runtime.

[3] Template Method defines the skeleton of an algorithm as an abstract class, allowing its subclasses to provide concrete behavior.

[4] Visitor lets you add new operations to classes of different objects without altering their source code.

Each of these patterns provides a unique solution to common problems that arise when designing software. Understanding the different behavioral design patterns can help you choose the best approach to solving complex problems and help you improve the overall design of your code.


(A) Chain of Responsibility Pattern

The Chain of Responsibility pattern is a design pattern used to handle requests or to forward requests to the next handler in a chain of handlers. The pattern provides a loosely coupled way of sending requests to one or more objects, while decoupling the sender and receiver of a request.

Here is an example implementation in Kotlin:

Chain of Responsibility Pattern
Chain of Responsibility Pattern

In the example, ConcreteHandler1 and ConcreteHandler2 are the concrete handlers in the chain. When a request is received, each handler checks if it can handle the request. If it can, it handles it and returns. If it cannot, it forwards the request to the next handler in the chain. The chain ends when the last handler in the chain cannot handle the request and returns.

The Chain of Responsibility pattern is useful when you want to decouple the sender and receiver of a request, and when you want to allow multiple objects to handle a request. The pattern also makes it easy to add or remove handlers from the chain, without affecting the other handlers in the chain.


* Disadvantages:

The disadvantages of the Chain of Responsibility pattern are:

  1. Increased complexity: It can make the system more complex if there are too many handlers in the chain. It can also make the system more difficult to understand and maintain.
  2. Reduced performance: It can reduce performance if the chain is long, as each handler must check if it can handle the request before forwarding it to the next handler.
  3. Reduced flexibility: It can reduce flexibility if the handlers are hard-coded, as it can be difficult to change the handlers in the chain or to add new handlers.
  4. Reduced control: It can reduce control if it is not clear which handler is responsible for handling a particular request. This can result in errors or unexpected results.
  5. Reduced visibility: It can reduce visibility if it is not clear which handler is handling a particular request, as it can be difficult to determine where an error occurred.

Despite these disadvantages, the Chain of Responsibility pattern is still a useful design pattern in certain situations where decoupled communication is required between objects and multiple handlers can handle the same request.


(B) Command Pattern

The Command pattern is a behavioral design pattern that allows objects to encapsulate requests as objects and pass these requests to different receivers. This pattern provides a way to decouple the senders of requests from their receivers, allowing the senders to be ignorant of the receivers and the receivers to be ignorant of the senders.

Here's a simple example of the Command pattern in Kotlin:

Command Pattern
Command Pattern

In this example, the LightOnCommand and LightOffCommand classes implement the Command interface and encapsulate the request to turn on and off the light, respectively. The Switch class uses a list of Command objects to keep track of the on and off commands. When the onButtonWasPushed or offButtonWasPushed methods are called, the appropriate command is executed.

The Command pattern allows you to encapsulate requests as objects and pass them around, which can make the code more flexible and easier to maintain. Additionally, the Command pattern makes it easier to implement undo and redo functionality, as the history of commands can be kept in a stack.


* Disadvantages:

The disadvantages of the Command pattern include:

  1. Increased complexity: The use of the Command pattern can add additional levels of complexity to a software system, especially when it comes to handling multiple commands.
  2. Increased number of objects: It can result in a large number of objects in the system, which can be challenging to manage and maintain.
  3. Decreased performance: The use of the Command pattern can result in decreased performance due to the overhead of creating and managing command objects.
  4. Difficulty in undo/redo operations: Implementing undo/redo operations with the Command pattern can be challenging, as it requires the ability to undo and reapply commands in the correct order.


(C) Mediator Pattern

The Mediator pattern is a behavioral design pattern that provides a centralized communication channel between objects. The goal of the Mediator pattern is to reduce coupling between objects and promote loose coupling. This is achieved by encapsulating the communication logic between objects within a mediator object.

Here is a simple code sample of the Mediator pattern in Kotlin:

Mediator Pattern
Mediator Pattern

In this example, the ChatRoom class acts as the mediator, which handles communication between the User objects. The User objects communicate with each other through the mediator, which encapsulates the communication logic and reduces the coupling between the objects.

Note: This is just a basic example to illustrate the concept of the Mediator pattern. In a real-world scenario, the mediator would typically handle much more complex communication between objects.


* Disadvantages:

The disadvantages of the Mediator pattern are:

  1. Increased Complexity: It can add complexity to the overall design of the application, as it involves creating additional objects to handle communication between objects.
  2. Hard to Test: This pattern can make it harder to test individual objects, as the communication logic is encapsulated within the mediator. This requires testing the entire mediator in addition to individual objects, making the testing process more complex.
  3. Increased Coupling: Although the Mediator pattern reduces coupling between objects, it still requires objects to have a reference to the mediator. This increases coupling between the objects and the mediator, making it harder to change the implementation of the mediator without affecting the objects that use it.
  4. Performance Overhead: It can introduce additional overhead to the system, as communication between objects is routed through the mediator. This can impact performance, especially in high-performance systems.
  5. Tight Coupling with the Mediator: It can create tight coupling between objects and the mediator. This makes it harder to change or replace the mediator, as objects are tightly coupled to it.


(D) Observer Pattern

The Observer pattern is a behavioral design pattern that defines a one-to-many relationship between objects, where one object (the subject) is being observed by multiple objects (observers). When the subject changes state, it notifies all its observers, who then update their state accordingly.

The key elements of the Observer pattern are:

  1. Subject: The object being observed. It stores a list of observers and provides methods to add and remove observers. It also notifies the observers of any changes to its state.
  2. Observer: The objects observing the subject. It has a method to update its state when the subject changes.
  3. ConcreteSubject: The concrete implementation of the subject. It stores the state of the subject and implements the methods to add and remove observers.
  4. ConcreteObserver: The concrete implementation of the observer. It stores a reference to the subject and implements the update method to update its state when the subject changes.

Here is an example of the Observer pattern in Kotlin:

Observer Pattern
Observer Pattern

In this example, the WeatherData object acts as the subject and the TemperatureDisplay object acts as the observer. The TemperatureDisplay object registers itself with the WeatherData object and gets notified of any changes to its temperature. When the temperature changes, the WeatherData object notifies all its observers, and the TemperatureDisplay object updates its display accordingly.


* Disadvantages:

The disadvantages of the Observer pattern are:

  1. Complexity: It can lead to a complex system if not implemented properly. The number of objects and relationships between them can become difficult to manage and maintain.
  2. Performance: It can result in a performance penalty, particularly if it is used in large systems with many observers. Each time a subject changes, it has to notify all its observers, leading to a lot of updates and events that can slow down the system.
  3. Coupling: It can increase coupling between objects, as they are tightly coupled with the subject they are observing. This makes it more difficult to make changes to the system without affecting the observer.
  4. Inflexibility: If the observer is dependent on the subject, it can become inflexible and difficult to change. It can also become difficult to add new observers or remove existing ones without affecting the subject.
  5. Unnecessary updates: Observers can receive updates even if they are not needed. This can result in unnecessary computation, leading to decreased performance.


(E) Template Pattern

The Template pattern is a behavioral design pattern that defines the skeleton of an algorithm in a method, called a template method, which defers some steps to subclasses. It lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.

Here’s an example of the Template pattern in Kotlin:

Template Pattern
Template Pattern

In this example, the Game class defines the template method play(), which calls the three methods initialize(), startPlay(), and endPlay() in a specific order. The Cricket and Football classes extend the Game class and implement the three methods. When the play() method is called, the algorithm is executed and the steps are performed in the order defined in the template method.


* Disadvantages:

The disadvantages of the Template Method pattern are:

  1. Inflexibility: It is not flexible enough as it specifies a fixed structure for an algorithm and this structure cannot be changed easily.
  2. Complexity: It can make the code more complex if it is used improperly.
  3. Rigidity: This pattern is often considered too rigid, as it forces the developer to use a specific structure for the algorithm, and this can lead to a lack of creativity.
  4. Increased Code Duplication: In some cases, the same code blocks can be repeated in different templates, leading to increased code duplication.
  5. Hard to maintain: If the algorithm changes frequently, it becomes harder to maintain the code because every change will have to be made in all the templates that use the same structure.


#softwaredesignpatterns #designpatterns?#designpattern?#android?#androiddeveloper?#androiddevelopers?#androiddevelopment?#androiddev?#androidstudio?#androidengineer?#androidapplication?#androidapp?#kotlin?#kotlindeveloper?#kotlinandroid?#java?#javaprogramming?#javadeveloper?#software?#softwaredevelopment?#softwareengineer?#softwareengineering?#softwaredesign?#softwarearchitecture?#coding?#coders?#pythonprogramming?#csharp?#golang?#webdevelopment?#phpdevelopers?#phpdevelopment

要查看或添加评论,请登录

社区洞察

其他会员也浏览了