pattern Archives - Welcome To Golang By Example https://vikasboss.github.io/tag/pattern/ Fri, 27 Dec 2019 16:39:06 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.1 https://i0.wp.com/golangbyexamples.com/wp-content/uploads/2021/05/cropped-go_border-1.png?fit=32%2C32&ssl=1 pattern Archives - Welcome To Golang By Example https://vikasboss.github.io/tag/pattern/ 32 32 159787465 Template Method Design Pattern in Go (Golang) https://vikasboss.github.io/template-method-design-pattern-golang/ https://vikasboss.github.io/template-method-design-pattern-golang/#comments Sat, 30 Nov 2019 13:28:50 +0000 https://vikasboss.github.io/?p=724 Note: Interested in understanding how all other design patterns can be implemented in GO. Please see this full reference – All Design Patterns in Go (Golang) Introduction: Template Method Design Pattern is...

The post Template Method Design Pattern in Go (Golang) appeared first on Welcome To Golang By Example.

]]>
Note: Interested in understanding how all other design patterns can be implemented in GO. Please see this full reference – All Design Patterns in Go (Golang)

Introduction:

Template Method Design Pattern is a behavioral design pattern that lets you define a template or algorithm for a particular operation.  Let’s understand the template design pattern with an example.

Consider the example of One Time Password or OTP. There are different types of OTP that can be triggered for eg. OTP can be SMS OTP or EMAIL OTP.  But irrespective it is an SMS OTP or EMAIL OTP,  the entire steps of the OTP process are the same.  The steps are

  • Generate a random n digit number. 
  • Save this number in the cache for later verification. 
  • Prepare the content
  • Send the notification
  • Publish the metrics

Even in the future let’s say a push notification OTP is introduced but still it will go through the above steps.

In such scenarios when the steps of a particular operation are the same but the steps of the operations can be implemented in a different way by different implementors , then that becomes a candidate for the Template Method Design Pattern. We define a template or algorithm which comprises of a fixed number of methods. The implementer of the operation overrides the methods of the template.

Now check out the below code example.

  • iOtp represents an interface that defines the set of methods that any otp type should implement
  • sms and email are the implementors of iOtp interface
  • otp is the struct which defines the template method genAndSendOTP(). otp embeds iOtp interface. 

Important: The combination of iOtp interface and otp struct provides the capabilities of Abstract Class in go. For reference see

Example

otp.go

package main

type iOtp interface {
    genRandomOTP(int) string
    saveOTPCache(string)
    getMessage(string) string
    sendNotification(string) error
    publishMetric()
}

type otp struct {
    iOtp iOtp
}

func (o *otp) genAndSendOTP(otpLength int) error {
    otp := o.iOtp.genRandomOTP(otpLength)
    o.iOtp.saveOTPCache(otp)
    message := o.iOtp.getMessage(otp)
    err := o.iOtp.sendNotification(message)
    if err != nil {
        return err
    }
    o.iOtp.publishMetric()
    return nil
}

sms.go

package main

import "fmt"

type sms struct {
    otp
}

func (s *sms) genRandomOTP(len int) string {
    randomOTP := "1234"
    fmt.Printf("SMS: generating random otp %s\n", randomOTP)
    return randomOTP
}

func (s *sms) saveOTPCache(otp string) {
    fmt.Printf("SMS: saving otp: %s to cache\n", otp)
}

func (s *sms) getMessage(otp string) string {
    return "SMS OTP for login is " + otp
}

func (s *sms) sendNotification(message string) error {
    fmt.Printf("SMS: sending sms: %s\n", message)
    return nil
}

func (s *sms) publishMetric() {
    fmt.Printf("SMS: publishing metrics\n")
}

email.go

package main

import "fmt"

type email struct {
    otp
}

func (s *email) genRandomOTP(len int) string {
    randomOTP := "1234"
    fmt.Printf("EMAIL: generating random otp %s\n", randomOTP)
    return randomOTP
}

func (s *email) saveOTPCache(otp string) {
    fmt.Printf("EMAIL: saving otp: %s to cache\n", otp)
}

func (s *email) getMessage(otp string) string {
    return "EMAIL OTP for login is " + otp
}

func (s *email) sendNotification(message string) error {
    fmt.Printf("EMAIL: sending email: %s\n", message)
    return nil
}

func (s *email) publishMetric() {
    fmt.Printf("EMAIL: publishing metrics\n")
}

main.go

package main

import "fmt"

func main() {
    smsOTP := &sms{}
    o := otp{
        iOtp: smsOTP,
    }
    o.genAndSendOTP(4)
    fmt.Println("")
    emailOTP := &email{}
    o = otp{
        iOtp: emailOTP,
    }
    o.genAndSendOTP(4)
}

Output:

SMS: generating random otp 1234
SMS: saving otp: 1234 to cache
SMS: sending sms: SMS OTP for login is 1234
SMS: publishing metrics

EMAIL: generating random otp 1234
EMAIL: saving otp: 1234 to cache
EMAIL: sending email: EMAIL OTP for login is 1234
EMAIL: publishing metrics

Full Working Code:

package main

import "fmt"

type iOtp interface {
    genRandomOTP(int) string
    saveOTPCache(string)
    getMessage(string) string
    sendNotification(string) error
    publishMetric()
}

type otp struct {
    iOtp iOtp
}

func (o *otp) genAndSendOTP(otpLength int) error {
    otp := o.iOtp.genRandomOTP(otpLength)
    o.iOtp.saveOTPCache(otp)
    message := o.iOtp.getMessage(otp)
    err := o.iOtp.sendNotification(message)
    if err != nil {
        return err
    }
    o.iOtp.publishMetric()
    return nil
}

type sms struct {
    otp
}

func (s *sms) genRandomOTP(len int) string {
    randomOTP := "1234"
    fmt.Printf("SMS: generating random otp %s\n", randomOTP)
    return randomOTP
}

func (s *sms) saveOTPCache(otp string) {
    fmt.Printf("SMS: saving otp: %s to cache\n", otp)
}

func (s *sms) getMessage(otp string) string {
    return "SMS OTP for login is " + otp
}

func (s *sms) sendNotification(message string) error {
    fmt.Printf("SMS: sending sms: %s\n", message)
    return nil
}

func (s *sms) publishMetric() {
    fmt.Printf("SMS: publishing metrics\n")
}

type email struct {
    otp
}

func (s *email) genRandomOTP(len int) string {
    randomOTP := "1234"
    fmt.Printf("EMAIL: generating random otp %s\n", randomOTP)
    return randomOTP
}

func (s *email) saveOTPCache(otp string) {
    fmt.Printf("EMAIL: saving otp: %s to cache\n", otp)
}

func (s *email) getMessage(otp string) string {
    return "EMAIL OTP for login is " + otp
}

func (s *email) sendNotification(message string) error {
    fmt.Printf("EMAIL: sending email: %s\n", message)
    return nil
}

func (s *email) publishMetric() {
    fmt.Printf("EMAIL: publishing metrics\n")
}

func main() {
    smsOTP := &sms{}
    o := otp{
        iOtp: smsOTP,
    }
    o.genAndSendOTP(4)
    fmt.Println("")
    emailOTP := &email{}
    o = otp{
        iOtp: emailOTP,
    }
    o.genAndSendOTP(4)
}

Output:

SMS: generating random otp 1234
SMS: saving otp: 1234 to cache
SMS: sending sms: SMS OTP for login is 1234
SMS: publishing metrics

EMAIL: generating random otp 1234
EMAIL: saving otp: 1234 to cache
EMAIL: sending email: EMAIL OTP for login is 1234
EMAIL: publishing metrics

The post Template Method Design Pattern in Go (Golang) appeared first on Welcome To Golang By Example.

]]>
https://vikasboss.github.io/template-method-design-pattern-golang/feed/ 2 724
Factory Design Pattern in Go (Golang) https://vikasboss.github.io/golang-factory-design-pattern/ https://vikasboss.github.io/golang-factory-design-pattern/#comments Sat, 30 Nov 2019 09:33:49 +0000 https://vikasboss.github.io/?p=707 Note: Interested in understanding how all other design patterns can be implemented in GO. Please see this full reference – All Design Patterns in Go (Golang) Introduction:  Factory design pattern is a...

The post Factory Design Pattern in Go (Golang) appeared first on Welcome To Golang By Example.

]]>
Note: Interested in understanding how all other design patterns can be implemented in GO. Please see this full reference – All Design Patterns in Go (Golang)

Introduction: 

Factory design pattern is a creational design pattern and it is also one of the most commonly used pattern. This pattern provides a way to hide the creation logic of the instances being created.
The client only interacts with a factory struct and tells the kind of instances that needs to be created. The factory class interacts with the corresponding concrete structs and returns the correct instance back.
In below example

  • We have iGun interface which defines all methods a gun should have
  • There is gun struct that implements the iGun interface.
  • Two concrete guns ak47 and maverick. Both embed gun struct and hence also indirectly implement all methods of iGun and hence are of iGun type
  • We have a gunFactory struct which creates the gun of type ak47 or maverick.
  • The main.go acts as a client and instead of directly interacting with ak47 or maverick, it relies on gunFactory to create instances of ak47 and maverick

UML Diagram:

Below is the corresponding mapping UML diagram with the example given above

Mapping:

The below table represents the mapping from the UML diagram actors to actual implementation actors in “Example” below

ProductFactorygunFactory.go
iProductiGun.go
Productgun.go
Concrete iProduct 1ak47go
Concrete iProduct 1maverick.go
Clientmain.go

Example: 

iGun.go

package main

type iGun interface {
    setName(name string)
    setPower(power int)
    getName() string
    getPower() int
}

gun.go

package main

type gun struct {
    name  string
    power int
}

func (g *gun) setName(name string) {
    g.name = name
}

func (g *gun) getName() string {
    return g.name
}

func (g *gun) setPower(power int) {
    g.power = power
}

func (g *gun) getPower() int {
    return g.power
}

ak47.go

package main

type ak47 struct {
    gun
}

func newAk47() iGun {
    return &ak47{
        gun: gun{
            name:  "AK47 gun",
            power: 4,
        },
    }
}

maverick.go

package main

type maverick struct {
    gun
}

func newMaverick() iGun {
    return &maverick{
        gun: gun{
            name:  "Maverick gun",
            power: 5,
        },
    }
}

gunFactory.go

package main

import "fmt"

func getGun(gunType string) (iGun, error) {
    if gunType == "ak47" {
        return newAk47(), nil
    }
    if gunType == "maverick" {
        return newMaverick(), nil
    }
    return nil, fmt.Errorf("Wrong gun type passed")
}

main.go

package main

import "fmt"

func main() {
    ak47, _ := getGun("ak47")
    maverick, _ := getGun("maverick")
    printDetails(ak47)
    printDetails(maverick)
}

func printDetails(g iGun) {
    fmt.Printf("Gun: %s", g.getName())
    fmt.Println()
    fmt.Printf("Power: %d", g.getPower())
    fmt.Println()
}

Output:

Gun: AK47 gun
Power: 4
Gun: Maverick gun
Power: 5

Full Working Code:

package main

import "fmt"

type iGun interface {
    setName(name string)
    setPower(power int)
    getName() string
    getPower() int
}

type gun struct {
    name  string
    power int
}

func (g *gun) setName(name string) {
    g.name = name
}

func (g *gun) getName() string {
    return g.name
}

func (g *gun) setPower(power int) {
    g.power = power
}

func (g *gun) getPower() int {
    return g.power
}

type ak47 struct {
    gun
}

func newAk47() iGun {
    return &ak47{
        gun: gun{
            name:  "AK47 gun",
            power: 4,
        },
    }
}

type maverick struct {
    gun
}

func newMaverick() iGun {
    return &maverick{
        gun: gun{
            name:  "Maverick gun",
            power: 5,
        },
    }
}

func getGun(gunType string) (iGun, error) {
    if gunType == "ak47" {
        return newAk47(), nil
    }
    if gunType == "maverick" {
        return newMaverick(), nil
    }
    return nil, fmt.Errorf("Wrong gun type passed")
}

func main() {
    ak47, _ := getGun("ak47")
    maverick, _ := getGun("maverick")
    printDetails(ak47)
    printDetails(maverick)
}

func printDetails(g iGun) {
    fmt.Printf("Gun: %s", g.getName())
    fmt.Println()
    fmt.Printf("Power: %d", g.getPower())
    fmt.Println()
}

Output:

Gun: AK47 gun
Power: 4
Gun: Maverick gun
Power: 5

The post Factory Design Pattern in Go (Golang) appeared first on Welcome To Golang By Example.

]]>
https://vikasboss.github.io/golang-factory-design-pattern/feed/ 2 707
Memento Design Pattern in Go (Golang) https://vikasboss.github.io/memento-design-pattern-go/ https://vikasboss.github.io/memento-design-pattern-go/#comments Fri, 29 Nov 2019 19:11:34 +0000 https://vikasboss.github.io/?p=694 Note: Interested in understanding how all other design patterns can be implemented in GO. Please see this full reference – All Design Patterns in Go (Golang) Introduction: Memento design pattern is a...

The post Memento Design Pattern in Go (Golang) appeared first on Welcome To Golang By Example.

]]>
Note: Interested in understanding how all other design patterns can be implemented in GO. Please see this full reference – All Design Patterns in Go (Golang)

Introduction:

Memento design pattern is a behavioral design pattern. It allows us to save checkpoints for an object and thus allow an object to revert to its previous state. Basically it helps in undo-redo operations on an object. Below are the design components of the Memento Design Pattern.

  • Originator: It is the actual object whose state is saved as a memento. 
  • Memento: This is the object which saves the state of the originator
  • Caretaker: This is the object that saves multiple mementos. Given an index, it returns the corresponding memento. 

The originator defines two methods. savememento() and restorememento()

  • savememento()- in this method the originator saves its internal state into a memento object.
  • restorememento()- this method takes input as a memento object. The originator restores itself to the pass memento.  Hence a previous state is restored.

Practical Example:

originator.go

package main

type originator struct {
    state string
}

func (e *originator) createMemento() *memento {
    return &memento{state: e.state}
}

func (e *originator) restorememento(m *memento) {
    e.state = m.getSavedState()
}

func (e *originator) setState(state string) {
    e.state = state
}

func (e *originator) getState() string {
    return e.state

memento.go

package main

type memento struct {
    state string
}

func (m *memento) getSavedState() string {
    return m.state
}

caretaker.go

Notice that the caretaker contains the mementoArray which holds all the memento.

package main

type caretaker struct {
    mementoArray []*memento
}

func (c *caretaker) addMemento(m *memento) {
    c.mementoArray = append(c.mementoArray, m)
}

func (c *caretaker) getMenento(index int) *memento {
    return c.mementoArray[index]
}

main.go

package main

import "fmt"

func main() {
    caretaker := &caretaker{
        mementoArray: make([]*memento, 0),
    }
    originator := &originator{
        state: "A",
    }
    fmt.Printf("Originator Current State: %s\n", originator.getState())
    caretaker.addMemento(originator.createMemento())
    
    originator.setState("B")
    fmt.Printf("Originator Current State: %s\n", originator.getState())
    
    caretaker.addMemento(originator.createMemento())
    originator.setState("C")
    
    fmt.Printf("Originator Current State: %s\n", originator.getState())
    caretaker.addMemento(originator.createMemento())
    
    originator.restorememento(caretaker.getMenento(1))
    fmt.Printf("Restored to State: %s\n", originator.getState())
    
    originator.restorememento(caretaker.getMenento(0))
    fmt.Printf("Restored to State: %s\n", originator.getState())
}

Output:

originator Current State: A
originator Current State: B
originator Current State: C
Restored to State: B
Restored to State: A

Full Working Code:

package main

import "fmt"

type originator struct {
    state string
}

func (e *originator) createMemento() *memento {
    return &memento{state: e.state}
}

func (e *originator) restoreState(m *memento) {
    e.state = m.getSavedState()
}

func (e *originator) setState(state string) {
    e.state = state
}

func (e *originator) getState() string {
    return e.state
}

type memento struct {
    state string
}

func (m *memento) getSavedState() string {
    return m.state
}

type caretaker struct {
    mementoArray []*memento
}

func (c *caretaker) addMemento(m *memento) {
    c.mementoArray = append(c.mementoArray, m)
}

func (c *caretaker) getMenento(index int) *memento {
    return c.mementoArray[index]
}

func main() {
    caretaker := &caretaker{
        mementoArray: make([]*memento, 0),
    }
    originator := &originator{
        state: "A",
    }
    fmt.Printf("Originator Current State: %s\n", originator.getState())
    caretaker.addMemento(originator.createMemento())
    originator.setState("B")
    fmt.Printf("Originator Current State: %s\n", originator.getState())
    caretaker.addMemento(originator.createMemento())
    originator.setState("C")
    fmt.Printf("Originator Current State: %s\n", originator.getState())
    caretaker.addMemento(originator.createMemento())
    originator.restoreState(caretaker.getMenento(1))
    fmt.Printf("Restored to State: %s\n", originator.getState())
    originator.restoreState(caretaker.getMenento(0))
    fmt.Printf("Restored to State: %s\n", originator.getState())
}

Output:

originator Current State: A
originator Current State: B
originator Current State: C
Restored to State: B
Restored to State: A

The post Memento Design Pattern in Go (Golang) appeared first on Welcome To Golang By Example.

]]>
https://vikasboss.github.io/memento-design-pattern-go/feed/ 2 694
Observer Design Pattern in Go (Golang) https://vikasboss.github.io/observer-design-pattern-golang/ https://vikasboss.github.io/observer-design-pattern-golang/#comments Fri, 29 Nov 2019 18:10:48 +0000 https://vikasboss.github.io/?p=687 Note: Interested in understanding how all other design patterns can be implemented in GO. Please see this full reference – All Design Patterns in Go (Golang) Introduction: Observer Design Pattern is a...

The post Observer Design Pattern in Go (Golang) appeared first on Welcome To Golang By Example.

]]>
Note: Interested in understanding how all other design patterns can be implemented in GO. Please see this full reference – All Design Patterns in Go (Golang)

Introduction:

Observer Design Pattern is a behavioral design pattern. This pattern allows an instance (called subject) to publish events to other multiple instances (called observers).  These observers subscribe to the subject and hence get notified by events in case of any change happening in the subject.

Let’s take an example. In the E-Commerce website, many items go out of stock. There can be customers, who are interested in a particular item that went out of stock. There are three solutions to this problem

  1. The customer keeps checking the availability of the item at some frequency.
  2. E-Commerce bombard customers with all new items available which are in stock
  3. The customer subscribes only to the particular item he is interested in and gets notified in the case that item is available. Also, multiple customers can subscribe to the same product

Option 3 is most viable, and this is what Observer Patter is all about. The major components of the observer pattern are:

  1. Subject – It is the instance to which publishes an event when anything changes. 
  2. Observer – It subscribes to the subject and gets notified by the events.

Generally, Subject and Observer are implemented as an interface. Concrete implementation of both are used

UML Diagram:

Mapping:

The below table represents the mapping from the UML diagram actors to actual implementation actors in “Practical Example” below

Subjectsubject.go
Concrete Subjectitem.go
observerobserver.go
Concrete Observer 1customer.go
Clientmain.go

Practical Example:

subject.go

package main

type subject interface {
    register(Observer observer)
    deregister(Observer observer)
    notifyAll()
}

item.go

package main

import "fmt"

type item struct {
    observerList []observer
    name         string
    inStock      bool
}

func newItem(name string) *item {
    return &item{
        name: name,
    }
}

func (i *item) updateAvailability() {
    fmt.Printf("Item %s is now in stock\n", i.name)
    i.inStock = true
    i.notifyAll()
}

func (i *item) register(o observer) {
    i.observerList = append(i.observerList, o)
}

func (i *item) deregister(o observer) {
    i.observerList = removeFromslice(i.observerList, o)
}

func (i *item) notifyAll() {
    for _, observer := range i.observerList {
        observer.update(i.name)
    }
}

func removeFromslice(observerList []observer, observerToRemove observer) []observer {
    observerListLength := len(observerList)
    for i, observer := range observerList {
        if observerToRemove.getID() == observer.getID() {
            observerList[observerListLength-1], observerList[i] = observerList[i], observerList[observerListLength-1]
            return observerList[:observerListLength-1]
        }
    }
    return observerList
}

observer.go

package main

type observer interface {
    update(string)
    getID() string
}

customer.go

package main

import "fmt"

type customer struct {
    id string
}

func (c *customer) update(itemName string) {
    fmt.Printf("Sending email to customer %s for item %s\n", c.id, itemName)
}

func (c *customer) getID() string {
    return c.id
}

main.go

package main

func main() {
    shirtItem := newItem("Nike Shirt")
    observerFirst := &customer{id: "abc@gmail.com"}
    observerSecond := &customer{id: "xyz@gmail.com"}
    shirtItem.register(observerFirst)
    shirtItem.register(observerSecond)
    shirtItem.updateAvailability()
}

Output:

Item Nike Shirt is now in stock
Sending email to customer abc@gmail.com for item Nike Shirt
Sending email to customer xyz@gmail.com for item Nike Shirt

Full Working Code:

package main

import "fmt"

type subject interface {
    register(Observer observer)
    deregister(Observer observer)
    notifyAll()
}

type item struct {
    observerList []observer
    name         string
    inStock      bool
}

func newItem(name string) *item {
    return &item{
        name: name,
    }
}

func (i *item) updateAvailability() {
    fmt.Printf("Item %s is now in stock\n", i.name)
    i.inStock = true
    i.notifyAll()
}

func (i *item) register(o observer) {
    i.observerList = append(i.observerList, o)
}

func (i *item) deregister(o observer) {
    i.observerList = removeFromslice(i.observerList, o)
}

func (i *item) notifyAll() {
    for _, observer := range i.observerList {
        observer.update(i.name)
    }
}

func removeFromslice(observerList []observer, observerToRemove observer) []observer {
    observerListLength := len(observerList)
    for i, observer := range observerList {
        if observerToRemove.getID() == observer.getID() {
            observerList[observerListLength-1], observerList[i] = observerList[i], observerList[observerListLength-1]
            return observerList[:observerListLength-1]
        }
    }
    return observerList
}

type observer interface {
    update(string)
    getID() string
}

type customer struct {
    id string
}

func (c *customer) update(itemName string) {
    fmt.Printf("Sending email to customer %s for item %s\n", c.id, itemName)
}

func (c *customer) getID() string {
    return c.id
}

func main() {
    shirtItem := newItem("Nike Shirt")
    observerFirst := &customer{id: "abc@gmail.com"}
    observerSecond := &customer{id: "xyz@gmail.com"}
    shirtItem.register(observerFirst)
    shirtItem.register(observerSecond)
    shirtItem.updateAvailability()
}

Output:

Item Nike Shirt is now in stock
Sending email to customer abc@gmail.com for item Nike Shirt
Sending email to customer xyz@gmail.com for item Nike Shirt

The post Observer Design Pattern in Go (Golang) appeared first on Welcome To Golang By Example.

]]>
https://vikasboss.github.io/observer-design-pattern-golang/feed/ 2 687
Builder Pattern in GoLang https://vikasboss.github.io/builder-pattern-golang/ https://vikasboss.github.io/builder-pattern-golang/#comments Wed, 04 Sep 2019 17:58:52 +0000 https://vikasboss.github.io/?p=243 Definition: Builder Pattern is a creational design pattern used for constructing complex objects. Below is the UML diagram. Note: Interested in understanding how all other design patterns can be implemented in GO....

The post Builder Pattern in GoLang appeared first on Welcome To Golang By Example.

]]>
Definition:

Builder Pattern is a creational design pattern used for constructing complex objects. Below is the UML diagram.

Note: Interested in understanding how all other design patterns can be implemented in GO. Please see this full reference – All Design Patterns in Go (Golang)

UML Diagram

Mapping (Also Refer 5th point – Example)

Directordirector.go
Builder InterfaceiBuilder.go
Concrete Builder 1normalBuilder.go
Concrete Builder 2iglooBuilder.go
Producthouse.go

When To Use

  • Use Builder pattern when the object constructed is big and requires multiple steps. It helps in less size of the constructor.  The construction of the house becomes simple and it does not require a large constructor
  • When a different version of the same product needs to be created. For example, in the below code we see a different version of house ie. igloo and the normal house being constructed by iglooBuilder and normalBuilder
  • When half constructed final object should not exist. Again referring to below code the house created will either be created fully or not created at all. The Concrete Builder struct holds the temporary state of house object being created

Example:

iBuilder.go

package main

type iBuilder interface {
    setWindowType()
    setDoorType()
    setNumFloor()
    getHouse() house
}

func getBuilder(builderType string) iBuilder {
    if builderType == "normal" {
        return &normalBuilder{}
    }
    if builderType == "igloo" {
        return &iglooBuilder{}
    }
    return nil
}

normalBuilder.go

package main

type normalBuilder struct {
    windowType string
    doorType   string
    floor      int
}

func newNormalBuilder() *normalBuilder {
    return &normalBuilder{}
}

func (b *normalBuilder) setWindowType() {
    b.windowType = "Wooden Window"
}

func (b *normalBuilder) setDoorType() {
    b.doorType = "Wooden Door"
}

func (b *normalBuilder) setNumFloor() {
    b.floor = 2
}

func (b *normalBuilder) getHouse() house {
    return house{
        doorType:   b.doorType,
        windowType: b.windowType,
        floor:      b.floor,
    }
}

iglooBuilder.go

package main

type iglooBuilder struct {
    windowType string
    doorType   string
    floor      int
}

func newIglooBuilder() *iglooBuilder {
    return &iglooBuilder{}
}

func (b *iglooBuilder) setWindowType() {
    b.windowType = "Snow Window"
}

func (b *iglooBuilder) setDoorType() {
    b.doorType = "Snow Door"
}

func (b *iglooBuilder) setNumFloor() {
    b.floor = 1
}

func (b *iglooBuilder) getHouse() house {
    return house{
        doorType:   b.doorType,
        windowType: b.windowType,
        floor:      b.floor,
    }
}

house.go

package main

type house struct {
    windowType string
    doorType   string
    floor      int
}

director.go

package main

type director struct {
    builder iBuilder
}

func newDirector(b iBuilder) *director {
    return &director{
        builder: b,
    }
}

func (d *director) setBuilder(b iBuilder) {
    d.builder = b
}

func (d *director) buildHouse() house {
    d.builder.setDoorType()
    d.builder.setWindowType()
    d.builder.setNumFloor()
    return d.builder.getHouse()
}

main.go

package main

import "fmt"

func main() {
    normalBuilder := getBuilder("normal")
    iglooBuilder := getBuilder("igloo")

    director := newDirector(normalBuilder)
    normalHouse := director.buildHouse()

    fmt.Printf("Normal House Door Type: %s\n", normalHouse.doorType)
    fmt.Printf("Normal House Window Type: %s\n", normalHouse.windowType)
    fmt.Printf("Normal House Num Floor: %d\n", normalHouse.floor)

    director.setBuilder(iglooBuilder)
    iglooHouse := director.buildHouse()

    fmt.Printf("\nIgloo House Door Type: %s\n", iglooHouse.doorType)
    fmt.Printf("Igloo House Window Type: %s\n", iglooHouse.windowType)
    fmt.Printf("Igloo House Num Floor: %d\n", iglooHouse.floor)
}

Output:

Normal House Door Type: Wooden Door
Normal House Window Type: Wooden Window
Normal House Num Floor: 2

Igloo House Door Type: Snow Door
Igloo House Window Type: Snow Window
Igloo House Num Floor: 1

The post Builder Pattern in GoLang appeared first on Welcome To Golang By Example.

]]>
https://vikasboss.github.io/builder-pattern-golang/feed/ 2 243