Notes: Go Design Patterns - Factory Pattern

Notes: Go Design Patterns - Factory Pattern

This blog contains the implementation of Factory design pattern using SMS and email notification objects

ยท

2 min read

Table of contents

No heading

No headings in the article.

Factory pattern offloads the logic behind the creation of concrete objects. In Factory pattern, we create objects without exposing the creation logic to the client and refer to the newly created object using a common interface.

Let's try to understand this by using a notification system. Let's say we have two methods to deliver notifications to the users, one by SMS and the other by Email. The interface that defines a notification system can look like this:

type iNotificationService interface {
    notify(message string)
}

Now, both SMS and Email will use this interface to implement the notification system.

// sms set up
type sms struct{}

func (s *sms) notify(message string) {
    fmt.Printf("sms sent: %v\n", message)
}

// email set up
type email struct{}

func (e *email) notify(message string) {
    fmt.Printf("email sent: %v\n", message)
}

Now that both methods implement iNotificationService interface, we can create a factory that creates any of these objects by returning the interface:

func notificationServiceFactory(notificationType string) (iNotificationService, error) {
    if notificationType == "sms" {
        return &sms{}, nil // can be improved further with constructors
    } else if notificationType == "email" {
        return &email{}, nil
    } else {
        return nil, fmt.Errorf("invalid notification service")
    }
}

Now, we can have any of these objects we want without thinking about their implementations individually.

Complete code to test:

package main

import "fmt"

type iNotificationService interface {
    notify(message string)
}

// sms set up
type sms struct{}

func (s *sms) notify(message string) {
    fmt.Printf("sms sent: %v\n", message)
}

// email set up
type email struct{}

func (e *email) notify(message string) {
    fmt.Printf("email sent: %v\n", message)
}

func notificationServiceFactory(notificationType string) (iNotificationService, error) {
    if notificationType == "sms" {
        return &sms{}, nil // can be improved further with constructors
    } else if notificationType == "email" {
        return &email{}, nil
    } else {
        return nil, fmt.Errorf("invalid notification service")
    }
}

func main() {
    notificationService1, _ := notificationServiceFactory("sms")
    notificationService1.notify("otp - 007")

    notificationService2, _ := notificationServiceFactory("email")
    notificationService2.notify("password - 12345")
}
ย