Practical usage of design patterns in iOS
By: Ankit Garg
Tags: Swift, Programming, iOS, Coding, Design Patterns

What is the design pattern?

Design patterns are generic solutions to the problems that developers usually face, design patterns can be applied to our codebase for common problems.

In this article, we will walk through different types of pattern and their practical usage in our production codebase. There are three types of design patterns.

Creational: It describes how an object is created. The creational patterns aim to separate a system from how its objects are created, composed, and represented. A few types are Builder, Factory and Singleton. Let’s read about them in detail:

Builder

It allows you to create a complex system by providing step-by-step input, instead of all inputs upfront at initializer.

Problem Statement: We have a user detail model(Visitor ID, Name, Cart items counts etc.). All these detail may not be available at the initialization itself. What if the user updates their email ID sometime later?

Solution: We can use a builder pattern in such situations. We will create a UserBuilder class. We will provide inputs to the Builder class step by step. Upon building, it will provide the user model as an output.

Factory Pattern

It hides the object creation logic from the client. The client uses the same interface to create new types of object. It promotes the loose-coupling. It means the code interacts solely with the resultant interface so that it will work with any classes that implement that interface.

Problem Statment: User can be authenticated using multiple channels. We have to add/remove a channel without breaking other channels.

Solution: We can use a factory pattern to solve this issue. We will create AuthenticationFactory class. This class will return the channel object based on the type of authentication. Each authentication channel class will adhere to AuthenticationChannel interface and provide its own implementation.

Singleton Pattern

This pattern restricts the class to have only a single instance in the whole application life cycle. Every class referring to the instance of Singleton class have a reference of only one and the same object. Any modification/update done to the Singleton class reflects changes in all classes referring to singleton instances. Although, sometimes it can be considered anti-pattern as it difficult to debug the updates and once a Singleton instance is created, it gets destroyed after the application life cycle is completed. We have to choose wisely before using the singleton pattern. This is widely used by apple e.g. UserDefaults, FileManager and UIApplication etc. We can use a singleton pattern to create single instances of APIClient’s etc.

2. Structural Design Patterns: These design patterns are about organizing different classes and objects to form larger structures and provide new functionality while keeping these structures flexible and efficient. Few examples are Facade and Adapter. Let’s read about them in detail:

Facade

It provides a simple interface to a complex system. It hides the complexity of the system and the simple interface is provided to the client to access it. It also promotes decoupling the subsystem from its potentially many clients.

Problem Statement: We do not want the client to find out how to add to cart or update cart logic works. The client needs a simplified interface to the overall functionality of a complex subsystem.

Solution: We can create a CartManager class which provides an interface to update, add and delete item(s) methods. A use case is basically a class which required network manager for initialization, it gets data from the network and parses it. We can do a unit test easily just by injecting MockApiClient in CartManager. MockApiClient will get data from JSON(stubbing) files instead of making actual network calls.

Adapter

This pattern allows incompatible systems to work together. It Converts the interface of a class into another interface which clients expect.

Problem: We are using AFNetworking library to download and cache images. We have to change the image cache library.

Solution: We can provide an interface to download image which will internally use AFNetworking library to download the image. Our application class will call the interface to download image instead of calling the library directly. Whenever we want to change the cache library we can change in our interface class and the whole application will intact about changes.

3. Behavioural Design Patterns: It describes how objects communicate with each other. The interaction between the objects should be in such a way that they can easily talk to each other and still should be loosely coupled. An example is Momento, delegate and observer pattern.

Momento: It allows an object to store and restore to a previously saved state. It has three class.

Originator is the object to be saved or restored. Momento contains state of an object to be restored.

3. Caretaker object is responsible to restore object state from Memento.

Problem: We have to store the recent search history of a user in our application so that whenever they access the app again, we can show them their recent search list.

Solution: We can use momento pattern to store recent search in UserDefault. Once the user accesses the application, we can retrieve their recent searches.

Thanks for reading! 👍🏻 Please share your feedback, queries regarding any of the topics in comments below.

If you liked this blog, please hit the 👏 . Stay tuned for the next article of remaining design patterns.