Design Pattern, Rust, Software Development

Chain of Responsibility Pattern Example In Rust

This post shows a simple implementation of the Chain of Responsibility pattern in Rust. For example, we have a set of struct instances that check for a file, read it, and finally, display it. We could imagine these instances as machines, e.g., ReadJsonMachine.

Three Handlers Each With Unique Responsibility

For this post, we use three struct instances to represent a set of handlers for our Chain of Responsibility pattern example in Rust. Consider the following diagram. The three handlers are CheckFileTypeMachine, ReadJSONMachine, and DisplayJSONMachine.

Chain of Responsibility Pattern in Rust

Meanwhile, the ResponseToRequestConverter converts an output from one handler into an input for the next handler. This item allows for loosely coupling our three handlers.

Chain of Responsibility in Rust Codes – Groundwork

Before we get to the handler codes, let us define strut and traits that will underpin our actual handler Rust codes. First, we two traits that represent the incoming and outcoming data to and from a handler. We can think of them as request and response, respectively.

Along with these traits come two implementing structs that use HashMap. Therefore, we need to import the appropriate collection type, e.g., use std::collections::HashMap;.

Then, we define a trait that represents a handler.

Chain of Responsibility Handlers

Next, we define three structs that implement that Machine trait. First, we have a handler that checks for a file type. Suppose the file name does not end with .json, the Rust codes panic and return an error. Otherwise, it creates a response with the file type and path to the JSON file.

Second, we have another handler that reads the content of a JSON file. When it reads the JSON file successfully, it creates a response that contains the JSON data.

Note that we need to import the fs module, e.g.,  use std::fs; to read a JSON file.

Third, we have the last handler that prints out the JSON data.

Now, how do we chain the handlers?

Loose Coupling in Chain of Responsibility Design Pattern

For this post, we couple the handlers by using a loop and a response-to-request converter. First, we define the direction in which the data (request) flows using a loop. Second, the response-to-request converter allows us to transform a response from one handler into a request format for the next handler. As a result, the handlers do not know anything about the others in the chain.

When we run all the codes, we get the following output.

We tested the codes using Rust 1.59.00.

Other Design Patterns

For other design patterns in Rust, please read the post Design Patterns Are The Ultimate Toolkit For Programmers.


Got comments or suggestions? We disabled the comments on this site to fight off spammers, but you can still contact us via our Facebook page!.

You Might Also Like