What is the Composite Pattern?
The composite pattern is a design pattern in which a group of objects can be treated the same way as a single object.
The idea is to compose objects into tree structures to represent part-whole hierarchies.
How is this going to help us with validating user input?
User input fields tend to have many small rules that need to be followed in order for the input to be considered “valid”. Using the composite pattern can be an elegant way to break up this code into smaller units, and allow them to be easily added/removed/changed later.
Imagine you have a registration form in your application. Your registration form has 2 input fields:
Each of these fields has their own requirements for the user input to be considered “valid”.
- Must not be empty
- Must be a valid email format
- Must not be empty
- Must be at least 8 characters long
- Must have one uppercase letter, lowercase letter and a number
Let’s see some code!
In order to set this up, there are a few main sections:
- Validator Protocol
- Individual Validators
- Composite Validator
- Validator Configurator
- Example of it used
We’re going to create a protocol that every validator will conform to (the validators are the objects that will decide if the user input is valid or not).
Before creating the protocol, let’s create the result type that will be returned for each validator:
Each validator is going to respond with whether the input it was given was valid or not. If it is not valid, it will return some type of error explaining why.
Great, now let’s look at this validator protocol.
So, each validator is going to have a function that accepts the input as a
String and returns a
Before showing the individual validators, here are the errors that can be specified for invalid inputs:
Let’s take a look at how these validators are implemented.
Empty String Validator
Email Format Validator
Password Length Validator
Uppercase Letter Validator
… and just imagine I made a
LowercaseLetterValidator and a
ContainsNumberValidator. The implementations would be the same as the
UppercaseLetterValidator, just with different regex.
The whole idea behind this is that we will be able to compose all of those individual validators into a larger tree of validators and allow this tree to be used in the same way as if it were a leaf.
To do this, we are going to create the
CompositeValidator. This validator is going to be initialized with an array of validators. When it is called to validate, it will iterate through them and ask each individual one to validate the input.
For the sake of simplicity, it is just going to return the first invalid response. (You could, however, change the logic so that validators return arrays of errors for invalid responses, which I wrote about in this post)
Now we have all of the parts needed to compose the different validators, let’s create a configurator class to do that work.
This is a helper class to make the code easy to read, use, and change later.
You can see that both the email and password validators are actually just composites of other validators. And even the “passwordStrengthValidator” is a composite.
Example of it used
This will print the output:
invalid(EmailValidatorError.empty) invalid(EmailValidatorError.invalidFormat) valid invalid(PasswordValidatorError.empty) invalid(PasswordValidatorError.tooShort) invalid(PasswordValidatorError.noUppercaseLetter) valid
I think this is an interesting way to organize user input validating code. It provides a way to break up code into smaller, succinct units, and makes it simple to change code later.
If you have any comments/suggestions, hit me up on twitter or my email linked below!
Update: After some feedback, I changed some of the code to be more “swifty”