Design Patterns are an important ingredient of clean, clear, and scalable code. In this series, we have been exploring the various Design Patterns and how to use them with Golang. In this article, we are going to discuss Proxy Design Pattern in Golang.

Proxy Design Pattern, like an adapter pattern, is a structural Design Pattern. We have already discussed them in great detail (here) in previous posts.

Let us try to develop an intuition and then implement Proxy Design Pattern in Golang.

What is Proxy Design Pattern?

To understand this, let us understand, what is proxy. For Indian college grads, the first thing you remember about proxy is Proxy Attendance. When someone else marks your college attendance on your behalf, while you are still sleeping on your comfy bed. Another term would be proxy internet when you think like you are actually talking to the real internet, but you are actually talking to a local server kept in your campus, which in turn talks to the real internet.

In a nutshell, Proxy stands for “on behalf”  or “in place of”. That’s it. That tells us about the proxy design pattern.

In proxy design pattern, a resource (class/struct) acts or represents functionality similar to another resource on behalf of that resource. The end-user does not need to know about the underlying resource. It just interacts with the proxy resource. The interface exposed by the object and the proxy object is exactly identical, and thus there is no way the end-user can find out if he is dealing with the real object or proxy object.

 

Proxy Pattern

                                           Proxy Design Pattern

 

When to use Proxy Design Pattern?

Proxy Design Patterns should be used when we want to provide an object with extra security, functionality, or simplicity.  Proxy Objects are wrappers around the original/real objects that provide the real objects with this extra functionality.

Suppose we have a resource object, that holds some secret information. This is the real object. But now we want an extra layer of security around it. This right here is the use case of Proxy Design Pattern. We make a new object (embedding the original object), that implements the same interface as the original object. We then just tweak around with the implementation of the interface to provide it more security.
It always sounds confusing without getting your hands dirty with some code. So let us pick up this task and see how can we implement Proxy Design Pattern in Golang.

Types of Proxies:

  • Remote Proxy:
    This represents resources that are located outside your local machine on the internet. Any sort of interaction with these resources involves a great deal of serialization and deserialization. All that logic is wrapped into a proxy object which then is exposed to the client.
  • Protection Proxy: 
    As already discussed, sometimes we need to build an extra layer of security around the object. Again all that logic is placed in a proxy object. This is where Protection Proxy comes into the picture.There are other kinds of proxies as well, but more or less it is about the use case.
    Let us now dive into some code and implement the proxy pattern.

 

Implementation

First of all, let us define the interface and the real object that implements the interface.

type ObjectInterface interface {
  ReadDetails()
}

type Object struct {
  Details string
}

func (o *Object) ReadDetails() {
  fmt.Println(o.Details)
}

ObjectInterface is the interface and Object is the real object. We also see the manner in which the real object implements the interface. Now here comes the issue, we want to limit the access to the detail exposed by the real object. Let us see how we can use Proxy Object to do so.
Suppose we have a role tied to every accessor that tries to access the object, and we only want to reveal the details on an accessor whose role is Admin . To do so first define the Accessor type.

type Accessor struct {
  Role string
}

Now let us define a proxy object type. This object will embed both, the real object and the accessor.

type ProxyObject struct {
  Object
  Accessor
}

To make it exactly similar to the real object, we need to implement the ObjectInterface Interface with the Proxy Object. This where the trick lies. Since we have both, the accessor and the object in the proxy object, we can check the role of the accessor before reading the details of the real object. Let us see how this is done.

func (o *ProxyObject) ReadDetails() {
 if o.Role != "Admin" {
   fmt.Println("not allowed to access")
   return
 }
 fmt.Println(o.Details)
}

As can be seen, we first check the role of the accessor before reading the details from the object. Now if only the proxy object is exposed to the client (in a real-world application, the proxyObject has to be built on the runtime for every user when he is authenticated), there is no way he can read the underlying secret without having a proper role.
Let us finish the implementation with the driver code.

func main() {
  Ob := Object{
    Details: "Some secret",
  }

  AdminAccessor := Accessor{
    Role: "Admin",
  }

  NoNAdminAccessor := Accessor{
    Role: "NonAdmin",
  }
  
  AdminProxyOb := ProxyObject{
    Ob,
    AdminAccessor,
  }

  NoNAdminProxyOb := ProxyObject{
    Ob,
    NoNAdminAccessor,
  }

  NoNAdminProxyOb.ReadDetails()
  AdminProxyOb.ReadDetails()
}

Let us quickly see what is happening here, we make a real object,  an admin accessor, and a non-admin accessor. We then make two proxy objects, one with an admin accessor and the other with a non-admin accessor. And then call the ReadDetails functions with each of the proxy objects.

The outputs are on the expected lines

not allowed to access
Some secret

Hence, we see, how we can use proxy design patterns in Golang to provide extra function, security and simplicity to the underlying objects without disturbing their semantics.

 

We will be up with another post very soon, exploring more design patterns. In the meanwhile, readers can experiment with Proxy Design Pattern in Golang, and discover their use cases. Any information missed out in the article, please share in the comments, so that we all may learn from it.


0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *

Wordpress Social Share Plugin powered by Ultimatelysocial
error

Enjoy this blog? Please spread the word :)