Design Patterns with Swift: Quick look at a Strategy Pattern
Tags: ios, swift, designpatter, strategypattern
Published: 2017-11-20 09:53:05

---
title: "Design Patterns with Swift: Quick look at a Strategy Pattern"
published: true
description: Let’s take a quick look at one of the design patterns that should help us to write a good Object-Oriented code.
tags: iOS, Swift, design patter, strategy pattern
canonical_url: https://brightinventions.pl/blog/quick-look-on-a-strategy-pattern-using-swift/
---

Let's take a quick look at one of the design patterns that should help us to write a good Object-Oriented code.
The basic assumption of Strategy Pattern is that you can define many implementations that will conform to the protocol.

Take a look at a simple example that can be used on iOS applications.


Firstly, create a `protocol` which contains a method. In our case it will be:

## Define protocol

```swift
protocol ImageDataRepresentation {
    func dataRepresentationFrom(image: UIImage) -> Data?
}
```

## Create strategies

Ok, most of the iOS apps use an `UIImage` to represent images in applications. The `UIImage` instance can be used to produce two different data representations of image `UIImagePNGRepresentation` and  `UIImageJPEGRepresentation`. Let's create classes that handle this stuff.

```swift
class JPEGImageRepresentation: ImageDataRepresentation {
    func dataRepresentationFrom(image: UIImage) -> Data? {
        print("JPEGImageRepresentation strategy called")
        guard let data = UIImageJPEGRepresentation(image, 1.0) else {
            return nil
        }
        return data
    }
}

class PNGImageRepresentation: ImageDataRepresentation {
    func dataRepresentationFrom(image: UIImage) -> Data? {
        print("PNGImageRepresentation strategy called")
        guard let data = UIImagePNGRepresentation(image) else {
            return nil
        }
        return data
    }
}
```

Now, as you can see - both classes conforms to the `ImageRepresentation` protocol but they differ in implementation. Each class represents a different **strategy**.

## Create client

The last thing - creating a client that uses one of the `ImageRepresentation` strategies.

```swift
class ImageRepresenter {
    var strategy: ImageDataRepresentation

    init(strategy: ImageRepresentation) {
        self.strategy = strategy
    }

    func imageDataRepresentation(image: UIImage) -> Data? {
        return strategy.dataRepresentationFrom(image: image)
    }
}
```

## Usage

```swift
let image = UIImage(named: "i_am_super_sure_that_image_exist")!
let imageRepresenter = ImageRepresenter(strategy: PNGImageRepresentation())
let pngData = imageRepresenter.imageDataRepresentation(image: image)

imageRepresenter.strategy = JPEGImageRepresentation()
let jpegData = imageRepresenter.imageDataRepresentation(image: image)
```

## Conclusions

The cool thing about Strategy Pattern is that we can change our strategy at runtime.
While using the Strategy Pattern we definitely conform to "Open-Close" SOLID principle. Our client is open for extensions by changing the strategy without changing the client implementation(close for modification). Also, the `ImageRepresenter` with Strategy Pattern included will be easiest to test.

Let's think how the above code could look like without Strategy Pattern:

### Using Switch

```swift
enum ImageRepresentation {
    case jpeg
    case png
}

class ImageRepresenter {
    func imageDataRepresentation(_ representation: ImageRepresentation) {
            switch representation {
            case .jpeg:
                return UIImageJPEGRepresentation(image)
            case .png:
                return UIImagePNGRepresentation(image)
            }
        }

}
```


### or using multiple functions

```swift
class ImageRepresenter {
    func pngDataRepresentation(image: UIImage) -> Data? {
        return UIImagePNGRepresentation(image)
    }

    func jpegDataRepresentation(image: UIImage) -> Data? {
        return UIImageJPEGRepresentation(image, 1.0)
    }
}
```

Both of these solutions definitely are not on the same line with CleanCode. Also, it might be hard to maintain that kind of code. The switch statement can grow with the next cases - what if we had to handle a 10, 20 or 100 strategies? The second one using multiple functions is also bad because we will continue duplicating the similar methods to handle each case. This few arguments should convince you to use Strategy Pattern. And last but not least, this two examples breakes the Open-Close principle.


Originally published at [brightinventions.pl](https://brightinventions.pl/blog/) on October 9, 2017.


By Kamil Wysocki, Software Engineer @ Bright Inventions
[Blog](https://wysockikamil.com), [Twitter](htpps://twitter.com/kamwysoc)