Calculator application

In this case study we will create a very simple calculator application. This application will give the user the ability to add, subtract, multiply, and divide whole or decimal numbers.

We will not go through how to set up the application or the UI design in this section. We will leave that up to you, the reader. This will let you design the UI as you want to and also allow you to build the application as an iOS or an OS X application. You could even build it as a Linux-based application since Swift is now open source.

You can download my iOS calculator application with the code bundle for this book. My design looks like the following screenshot:

Calculator application

Now let's look at the requirements.

Here are the requirements for our application:

Before reading further, based on these requirements see what type of design you come up with. Once you have worked out your design, continue reading and compare your design with the one we present.

The underlying philosophy behind our design is going to be making it easy to add new features in the future. We may be starting off with a basic calculator but eventually we will probably want to add additional features such as sine, cosine, tangent, or other scientific functions. Just like the SQLite.swift case study, there is a design pattern that can help us. The pattern we will use for this calculator example is the command pattern.

In order to understand how to design our commands, we need to understand how our calculator should work. The following steps should achieve this:

What these steps show us is that, each time the user presses a number button, we update the display. Whenever the user presses a command button (addition, subtraction, multiplication, division, or equals) we need to perform the function from the last command key that was pressed on the calculator's current value with the number that is currently being displayed.

So let's look at how we would write our command structures. We will need to start by creating a protocol that all command types must conform to. The following code shows what our command protocol looks like:

This protocol defines a method named execute. This method will take two values of the Double type, perform some function on those two numbers, and then return a new value of the Double type. This method is designed to encapsulate the logic needed to perform the mathematical function represented by the command type and return the results.

Now let's look at our addition, subtraction, multiplication, and division types that will conform to the command protocol that we just defined.

Each of these command types conforms to the CommandProtocol protocol by implementing the execute() method. The execute() method performs the appropriate function on the two values that are passed in and then returns the results.

Now let's create our Calculator type, which will use the command types to perform our calculations:

Our Calculator type has two properties. The first property is of the Double type and is named currentValue. This property will keep track of the current value of our calculation. The second property is an optional of the CommandProtocol type and is named lastCommand. This property will store the last command submitted to the calculator.

We have two methods in our Calculator structure. The first method, named clear(), simply sets the currentValue property to 0. The second method, named commandEntered(), accepts two arguments. The first argument of the Double type is named newNumber and the second argument of the CommandProtocol type is nextCommand.

The commandEntered method starts off by checking to see if the lastCommand property contains an instance of a type that conforms to the CommandProtocol. If it does contain an instance we will call the execute() method of the instance. The execute() method will perform some functionality and then return a new value. This new value will then be set as the current value for the calculator. The calculator does not know, or care, exactly what function the execute() method will perform; all it knows is that it needs to call that method. This is how the command pattern is designed to work.

Now let's see how we would use the Calculator class by looking at how we use it in the iOS example that comes with the downloaded code for this book. In the example we use instances of the UIbutton class for each of the buttons on our calculator. In the UIButton class, we have a property named tag that we can use to assign a unique number to each of our buttons that identifies the button that was tapped. In our example, the following tags are assigned to each button:

The method that handles the touch events for the command buttons look like this:

Within the CommandButtonTapped() method, we use a switch statement to pick the button that was tapped. We then call the commandEntered() method of the Calculator instance and pass it the current number that is being displayed (entered by the user) and an instance of the appropriate command type.

When we need to add additional functionality to our calculator, all we need to do is to create additional types that conform to the CommandProtocol protocol that encapsulates the logic for this new functionality. We are then able to pass instances of these new types to our calculator. The ability to easily add new functionality to our applications is what makes the command pattern so powerful.