Do you ever find yourself writing a lengthy
switch statements or
if statements structured like a switch. Luckily there is the Strategy Pattern to help alleviate this complex, sometimes unintelligible code. You may have also noticed that this code can have quite a high Cyclomatic Complexity.
Let's take a look at an example of a lengthy
switch statement. The code below is checking a user's role and if they have read or write permissions. Now this is a contrived example but the pattern still applies.
Here we can see the complexity is becoming unweildy, sure there are ways to clean this code up more with string manipulation of the urls and roles/permissions. The permissions check should be a single function call as well. Humor me and let's pursue the Strategy Pattern for now and we'll clean up the permissions check along the way.
First we will start off laying out the basic structure for our strategy. We will define a
UserRoleStrategy class with functions for each role and a default handler.
We are creating a function to handle each user role, similar to our switch statement. Now let's go ahead and add the logic for each user role. We will pull the logic out of our
switch and place it in the appropriate user role function.
That's still pretty messy, so let's refactor the permissions logic. This step is not strategy pattern related but will make the code more readable. Our strategy object allows us to refactor easily and contain the logic within it.
Refactor complete, now we have a strategy object with two private functions to handle our permission/url logic and our logging. We no longer rely on a switch statement to handle our user role logic but a full blown object that can be extended as needed. Note on line 53 we are instantiating our strategy object,
currentRoleHandler, and passing in the
user. We then use the square brackets to pass in our user role on line 57,
currentRoleHandler[user.role](). Resulting in a call to the correct function on our strategy object.
That's it, thanks for reading!