Lesson 4
Applying Behavioral Patterns in Real-World Scenarios
Applying Behavioral Patterns in Real-World Scenarios

We are advancing through our journey of building various real-world applications. We have explored the Command, Observer, and Strategy patterns in the previous units. In this unit, we will integrate all three behavioral patterns into different scenarios to solve real-world problems.

Before diving into the coding exercise, let's have a quick recap of what each pattern does. The Command pattern encapsulates a request as an object, allowing clients to parameterize and queue requests. The Observer pattern defines a one-to-many dependency between objects, ensuring that when one object changes state, all its dependents are notified and updated automatically. The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Clients can choose the algorithm to use at runtime.

Let us consider one scenario of using the Command and Observer patterns together to build a chat application.

Building a Chat Application

The Command pattern encapsulates a request as an object, supporting the parameterization of clients with different requests and enabling undoable operations. Here’s a quick sample demonstrating how to encapsulate the action of showing a message in the chat room:

Python
1from abc import ABC, abstractmethod 2 3class Command(ABC): 4 @abstractmethod 5 def execute(self): 6 pass

We define a base Command class with an abstract execute method. This serves as the blueprint for all command objects, ensuring they adhere to a common execution interface.

Python
1class ChatRoom: 2 def show_message(self, message): 3 print(f"Message: {message}")

Next, we define a ChatRoom class with a method to display and propagate messages. The send_message function in the ChatRoom class will be defined further down below.

Python
1class ChatCommand(Command): 2 def __init__(self, chat_room, message): 3 self.chat_room = chat_room 4 self.message = message 5 6 def execute(self): 7 self.chat_room.show_message(self.message) 8 self.chat_room.send_message(self.message)

The ChatCommand class inherits from Command and encapsulates the action of showing a message. When creating a ChatCommand, you set the message and the chat room where the message will be displayed, then execute this command to display the message.

Now, we integrate the Observer pattern to enable our chat application to notify users about incoming messages. Each User instance represents an observer that can receive messages, while the ChatRoom acts as the subject that notifies its users.

Python
1class User: 2 def __init__(self, name): 3 self.name = name 4 5 def receive_message(self, message): 6 print(f"{self.name} received message: {message}")

We define a User class where each user can receive and print messages. This will allow users to get real-time updates from the chat room.

Python
1class ChatRoom: 2 def __init__(self): 3 self.users = [] 4 5 def add_user(self, user): 6 self.users.append(user) 7 8 def show_message(self, message): 9 print(f"Message: {message}") 10 11 def send_message(self, message): 12 for user in self.users: 13 user.receive_message(message)

Here, the ChatRoom class is enhanced to hold a list of users and send messages to all users by iterating through the list, simulating the observer notification. Adding the Observer pattern ensures that new messages are immediately communicated to all users.

Now, we will combine both the Command and Observer patterns to create a functional chat application. You will use commands to handle user inputs and observers to manage message broadcasting. This integration increases the modularity and clarity of the application structure, making it easier to maintain and extend.

Intermediate steps to combine the patterns:
  1. Defining the ChatRoom
Python
1chat_room = ChatRoom()
  1. Creating User Instances
Python
1user1 = User("Alice") 2user2 = User("Bob")
  1. Adding Users to the ChatRoom
Python
1chat_room.add_user(user1) 2chat_room.add_user(user2)
  1. Creating and Executing a ChatCommand
Python
1chat_command = ChatCommand(chat_room, "Hello, everyone!") 2chat_command.execute()

This way, the chat room acts as a central hub, commands encapsulate user actions such as sending messages, and users observe and receive messages from the chat room.

Combined Code Structure

Below is the combined structure of our chat application, illustrating how the Command and Observer patterns work together:

Python
1from abc import ABC, abstractmethod 2 3class Command(ABC): 4 @abstractmethod 5 def execute(self): 6 pass 7 8class User: 9 def __init__(self, name): 10 self.name = name 11 12 def receive_message(self, message): 13 print(f"{self.name} received message: {message}") 14 15class ChatRoom: 16 def __init__(self): 17 self.users = [] 18 19 def add_user(self, user): 20 self.users.append(user) 21 22 def show_message(self, message): 23 print(f"Message: {message}") 24 25 def send_message(self, message): 26 for user in self.users: 27 user.receive_message(message) 28 29class ChatCommand(Command): 30 def __init__(self, chat_room, message): 31 self.chat_room = chat_room 32 self.message = message 33 34 def execute(self): 35 self.chat_room.show_message(self.message) 36 self.chat_room.send_message(self.message) 37 38if __name__ == "__main__": 39 chat_room = ChatRoom() 40 user1 = User("Alice") 41 user2 = User("Bob") 42 43 chat_room.add_user(user1) 44 chat_room.add_user(user2) 45 46 chat_command = ChatCommand(chat_room, "Hello, everyone!") 47 chat_command.execute() 48 # Outputs: 49 # Message: Hello, everyone! 50 # Alice received message: Hello, everyone! 51 # Bob received message: Hello, everyone!
Conclusion

By the end of this unit, you will have a functional chat application in which messages can be sent and received efficiently. You will also have a deeper understanding of how combining multiple behavioral patterns can solve complex real-world problems effectively. Let's get started with the practice section and see these concepts come to life in our chat application!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.