What is the Factory Design Pattern in Go?

Factory functions

First, we are going to build our Post struct and a PostFactory:

type Post struct {
    Content, Website, Author string
}

type PostFactory struct {
    Website, Author string
}

Now, we are going to create a function that will return another function. This way we can have multiple types of factories to create different types of objects:

func NewPostFactory(website string, author string) func(content string) *Post {
    return func(content string) *Post {
        return &Post{content, website, author}
    }
}

This function receives two strings as parameters and returns a function that receives another string and returns a pointer to a Post. Let’s see how this works on the main function.

Let’s assume I want to write a Post and cross-post it to Dev.to Hackernews.comand medium.com:

func main() {
    devPostFactory := NewPostFactory("DEV.to", "Tomassirio")
    mediumPostFactory := NewPostFactory("Medium.com", "Tomassirio")
    hackerNewsPostFactory := NewPostFactory("Hackernews.com", "Tomassirio")

    content := "This is what I'm Cross-Posting today!"

    devPost := devPostFactory(content)
    mediumPost := mediumPostFactory(content)
    hackerNewsPost := hackerNewsPostFactory(content)

    fmt.Println(devPost)
    fmt.Println(mediumPost)
    fmt.Println(hackerNewsPost)
}

In the first three lines, we are initializing the PostFactory’s we are going to use to create our cross-posts. As you can see, after creating the brief post, we can use these factories as functions that return the Posts.

Code

package main
import "fmt"
type Post struct {
Content, Website, Author string
}
type PostFactory struct {
Website, Author string
}
func NewPostFactory(website string, author string) func(content string) *Post {
return func(content string) *Post {
return &Post{content, website, author}
}
}
func main() {
devPostFactory := NewPostFactory("DEV.to", "Tomassirio")
mediumPostFactory := NewPostFactory("Medium.com", "Tomassirio")
hackerNewsPostFactory := NewPostFactory("Hackernews.com", "Tomassirio")
content := "This is what I'm Cross-Posting today!"
devPost := devPostFactory(content)
mediumPost := mediumPostFactory(content)
hackerNewsPost := hackerNewsPostFactory(content)
fmt.Println(devPost)
fmt.Println(mediumPost)
fmt.Println(hackerNewsPost)
}

Prototype factory

I didn’t really like this method, but you have to learn things before you can dislike them.

In this example, we are defining the type Website, which is actually a string, and an enum below where we declare the Websites that I’ll be posting this to:

type Website string

const (
    DEV         Website = "Dev.to"
    MEDIUM              = "Medium.com"
    HACKER_NEWS         = "Hackernews.com"
)

We then declare the function where we’ll create the post. There’s a default case where we can create an empty Post:

func NewPost(website Website) *Post {
    author := "Tomassirio"
    switch website {
    case DEV:
        return &Post{"", string(website), author}
    case MEDIUM:
        return &Post{"", string(website), author}
    case HACKER_NEWS:
        return &Post{"", string(website), author}
    default:
        return &Post{"", "", ""}
    }
}

Finally, we will apply these functions to the main function:

func main() {
    content := "This is what I'm Cross-Posting today!"

    devPost := NewPost(DEV)
    mediumPost := NewPost(MEDIUM)
    hackerNewsPost := NewPost(HACKER_NEWS)

    devPost.Content = content
    mediumPost.Content = content
    hackerNewsPost.Content = content

    fmt.Println(devPost)
    fmt.Println(mediumPost)
    fmt.Println(hackerNewsPost)
}

The results are always going to be the same.

Code

package main
import "fmt"
type Website string
const (
DEV Website = "Dev.to"
MEDIUM = "Medium.com"
HACKER_NEWS = "Hackernews.com"
)
type Post struct {
Content, Website, Author string
}
func NewPost(website Website) *Post {
author := "Tomassirio"
switch website {
case DEV:
return &Post{"", string(website), author}
case MEDIUM:
return &Post{"", string(website), author}
case HACKER_NEWS:
return &Post{"", string(website), author}
default:
return &Post{"", "", ""}
}
}
func main() {
content := "This is what I'm Cross-Posting today!"
devPost := NewPost(DEV)
mediumPost := NewPost(MEDIUM)
hackerNewsPost := NewPost(HACKER_NEWS)
devPost.Content = content
mediumPost.Content = content
hackerNewsPost.Content = content
fmt.Println(devPost)
fmt.Println(mediumPost)
fmt.Println(hackerNewsPost)
}

Free Resources

Attributions:
  1. undefined by undefined
Copyright ©2024 Educative, Inc. All rights reserved