Creating your own HTTP API wrapper library: Design Patterns

Tompee Balauag
Familiar Android
Published in
5 min readMay 24, 2018
“The dictionary definition of the word “design” displayed on a smartphone screen” by Edho Pratama on Unsplash

Note: This is the second part of the creating your own HTTP API wrapper library series. First part here.

Design patterns are important when developing reusable codes such as libraries. They can greatly help users by means of abstraction and developers in terms of scalability, maintainability and forward compatibility. There are different kinds of design patterns and we will only discuss those that will be helpful when designing an HTTP API wrapper library.

Creational Patterns

Creational patterns provides a way to create objects by abstracting the logic and intricacies from the client. It delegates the responsibility of instantiating (or reusing) objects away from the client.

  1. Factory Pattern

First on our list is the factory pattern. Factory pattern is one of the most used design pattern. This pattern provides an object without exposing the instantiation process. The returned objects can be referred through a common interface. First we define an interface and possible implementations.

Now we create our factory that returns concrete objects. The client will just know about the interface and will not be involved in instantiating these concrete types.

We define our SuperHeroFactory so we can access its methods without instantiating it. Now, the client can just pass the name of the desired superhero and the factory will be the one to instantiate it. This is useful in cases wherein a object instantiation is complicated and you do not want to delegate that responsibility to the client.

2. Singleton Pattern

Singleton pattern is one of the simplest design pattern. This pattern provides a way to create an object of a class while making sure that only a single instance of that particular class exist. This is useful for application wide services as an alternative for dependency injection. Let’s create our factory class from above as a generic singleton.

This generic approach allows you to create singletons with parameters (unlike object). Some noteworthy things in a good singleton implementation are lazy initialization and thread safety.

3. Builder Pattern

Builder pattern allows you to create an object in a step by step approach. It allows for object customization while abstracting object instantiation and assembly. In Kotlin, named arguments and default argument values are supported so in most cases, you wont need the builder pattern. But this can still be useful when working with Java, or large objects with a huge number of dependencies.

First, we define an interface or a model, whichever you prefer. In case of an interface, create a concrete implementation. Then we now create our builder.

The idea here is that our builder will be the one to build the hero instance. To do so, it requires some parameters. The builder will set some default values in case the client did not provide one. The most common structure for the builder pattern is, the builder is a nested class of the class being created (with the enclosing class having a private constructor to prevent bypassing the builder). You can choose whatever you like.

Structural Patterns

Structural patterns concern themselves with defining relationships between objects and classes.

  1. Bridge Pattern

First on our list is the bridge pattern. This pattern decouples an abstraction from the implementation and introduces a bridge between them.

Consider a case wherein you want to draw different shapes with different colors. This can be implemented by brute force but it is not scalable. Instead, we need to find a way to set the color we want in each shape object that we create. We define the drawing API as the implementation and the shape as the abstraction.

The DrawingAPI provides an interface for drawing different objects. DrawingAPI can have different methods such as drawing specific objects but for simplicity we will use only 1. Then we can create multiple concrete implementation of the DrawingAPI to customize the way we can draw objects. Now our shape class has a draw method. How convenient for us to have a “drawing implementor”. Maybe we can use it? You bet we can. We just need to pass an instance of the DrawingApi so our shape can delegate all drawing functions to the DrawingAPI object. This is why it is called bridging. The abstraction is being bridged to the implementation.

2. Facade Pattern

Facade pattern hides the complexity of a system and exposes only the minimum set of interface to interact with it. Let’s consider the example below.

Suppose we have an account manager that can lookup both in the database and cloud. Now, we can only expose the displayAccount to the client without it bothering about the complexities of the database queries, cloud login and data persistence.

3. Adapter Pattern

This pattern is pretty straightforward. In acts as an adapter for 2 incompatible interfaces. Examples include the adapters in RecyclerViews and ViewPagers. Let’s take a look at a simple example. Suppose we have 2 callbacks, one interfacing the client and one is a service interface from backend.

Our client callback has 2 methods, success and error, but our service callback has only 1 but with a parameter. We can create an adapter that implements the service callback and accepts an instance of the client callback. Whenever the service callback method is called, we parse the parameter and call the corresponding method in the client callback.

Behavioral Patterns

Behavioral patterns are concerned with the communication between objects.

Command Pattern

Let us define 3 constructs:

  • Receiver = target object. This is the object that is going to be acted upon.
  • Command = the class that will perform the action towards the receiver. It should know the receiver.
  • Invoker = the class that will invoke the command

To understand better let’s take a look at an example.

We define a common interface for commands that has an execute method. In functional programming, this can be a functional interface. Then we define a receiver class called Bicycle. This class can perform 2 actions, pedal and stop.

Now we create 2 commands called PedalCommand and StopCommand.

These commands know our bicycle instance as expected. They will perform the designated bicycle actions when their execute method is invoked. Now let is create our invoker.

Now our vehicle can now move. And it is decoupled from the actual action. Currently we move by means of pedaling. What if in the future we want to push our bike instead. We do not need to modify our invoker class for that.

There are other various design patterns out there and I encourage you to learn about them. The ones mentioned here are the most common and crucial in building our own HTTP wrapper API library. Stay tuned for the next part of the tutorial.

--

--