Proxy Pattern in Go
Tags: go, productivity, design, programming
Published: 2020-12-11 22:32:22

Hey there!

In this week's post, I'm bringing you the proxy design pattern. 

Proxies may be used for a lot of things, such as communication, logging, caching, etc. So in this post, I'm going to show you two implementations of it.

## Protection Proxy

Let's assume you have a car struct and a Driven interface that implements a Drive() function. Nothing too fancy for this example, but it will make a click in the end:

```golang
type Driven interface {
	Drive()
}

type Car struct{}

func (c *Car) Drive() {
	fmt.Println("Car is being driven")
}
```

The Car struct is implementing the Driven interface with the Drive() function.

So now you'd be able to just instantiate a car and make it drive regardless of the driver's condition. So for example, if our Car's driver was underage, there'd be nothing stopping him from driving the car. And that's a big 'no no' where I come from. 

Let's assume there is a Driver struct as well with just an Age attribute:

```golang
type Driver struct {
	Age int
}
```

So Let's create a CarProxy and a constructor for this:

```golang
type CarProxy struct {
	car    Car
	driver *Driver
}

func NewCarProxy(driver *Driver) *CarProxy {
	return &CarProxy{Car{}, driver}
}
```

The CarProxy will have a Car and a Driver as it's attributes and will receive the driver as a parameter. Since cars are cars and we don't care that much about them for this example, we are going to create a generic car for the car proxy.

So now we need to implement the Driven interface for the CarProxy and we are going to restrict the user from being underage to use this method:

```golang
func (c *CarProxy) Drive() {
	if c.driver.Age >= 16 {
		c.car.Drive()
	} else {
		fmt.Println("Driver too young!")
	}
}
```

Let's test the results in the main function:

```golang
	car := NewCarProxy(&Driver{12})
	car.Drive()
```

```bash
go run main.go
Driver too young!
```

But if we change the Driver's age to 22 for example

```bash
go run main.go
Car is being driven
```

As you can see we didn't have to add things to the car struct in order to get the restrictions we needed for it. Instead, we just applied those restrictions to an upper layer (or proxy) to make these modifications.

## Virtual Proxy

For this example let's assume you want to create an Image Drawer for different types of formats.

Then let's create an Image interface that will have a Draw() signature:

```golang
type Image interface {
	Draw()
}
```

Then we can create a struct for a Bitmap image which will be constructed from a filename:

```golang
type Bitmap struct {
	filename string
}

func NewBitmap(filename string) *Bitmap {
	fmt.Println("Loading image from", filename)
	return &Bitmap{filename: filename}
}

func (b *Bitmap) Draw() {
	fmt.Println("Drawing image", b.filename)
}

func DrawImage(image Image) {
	fmt.Println("About to draw the image")
	image.Draw()
	fmt.Println("Done drawing the image")
}
```

Again, nothing fancy. I also added a DrawImage method which would show the progress of the image while being drawn.

And this would work just fine:

```golang
	bmp := NewBitmap("demo.png")
	DrawImage(bmp)
```

```bash
go run main.go
                                                                           
Loading image from demo.png
About to draw the image
Drawing image demo.png
Done drawing the image
```

But there would be an issue if, for example, we used the constructor without storing it in a variable:

```golang
	_ = NewBitmap("demo.png")
```

```bash
Loading image from demo.png
```

Our constructor would be lying to us! And that's also a big 'no no' from where I come from.

So let's use a proxy for this issue. To be more specific, a Virtual Proxy. 

```golang
type LazyBitmap struct {
	filename string
	bitmap   *Bitmap
}

func NewLazyBitmap(filename string) *LazyBitmap {
	return &LazyBitmap{filename: filename}
}
```

Our LazyBitmap struct will store the filename and a bitmap but will only receive the filename while instantiated leaving the bitmap as nil attribute. 

This is because we don't want the bitmap to be created before being rendered! So Let's render it when we actually need it to be:

```golang
func (l *LazyBitmap) Draw() {
	if l.bitmap == nil {
		l.bitmap = NewBitmap(l.filename)
	}
	l.bitmap.Draw()
}
```

This way we won't be loading infinite instances of the bitmap.  It will mostly work as a singleton attribute.

```golang
	bmp := NewLazyBitmap("demo.png")
	DrawImage(bmp)
```

We now instantiate the bitmap as a LazyBitmap and we can still use the DrawImage() method because it will call the bitmap's Draw() method on the inside. However this time the result will be a little bit different:

```bash
go run main.go                                                                           

About to draw the image
Loading image from demo.png
Drawing image demo.png
Done drawing the image
```

As you can see. The image is now loaded after the Draw method is called and not before, which is what we wanted.


That's all for this week, I hope you are learning as much as I do with these posts.