DEV Community

Kittipat.po
Kittipat.po

Posted on • Updated on

Understanding the Factory Method Pattern in Go

Factory Method Pattern

The Factory Method Pattern introduces a novel concept, creating objects without having to specify their exact types. This pattern allows developers to encapsulate the process of object creation, abstracting it behind a common interface or base class. Subclasses or implementations of this interface furnish the necessary creation logic, enabling clients to generate objects without delving into intricate implementation details.

Implementing the Factory Method Pattern in Go

Picture yourself orchestrating an e-commerce symphony, where customers from around the globe make purchases, each with their preferred payment method. You're tasked with weaving together a seamless experience for credit cards, digital wallets, and more. Here's where the Factory Method Pattern steps in – it lets you harmoniously integrate different payment processors without causing a coding cacophony.

package main

import (
    "errors"
    "fmt"
)

// PaymentGatewayType defines the type of payment gateway.
type PaymentGatewayType int

const (
    PayPalGateway PaymentGatewayType = iota
    StripeGateway
)

// PaymentGateway represents the common interface for payment gateways.
type PaymentGateway interface {
    ProcessPayment(amount float64) error
}

// PayPalGateway is a concrete payment gateway.
type PayPalGateway struct{}

func (pg *PayPalGateway) ProcessPayment(amount float64) error {
    fmt.Printf("Processing PayPal payment of $%.2f\n", amount)
    // Simulate PayPal payment processing logic.
    return nil
}

// StripeGateway is another concrete payment gateway.
type StripeGateway struct{}

func (sg *StripeGateway) ProcessPayment(amount float64) error {
    fmt.Printf("Processing Stripe payment of $%.2f\n", amount)
    // Simulate Stripe payment processing logic.
    return nil
}

// NewPaymentGateway creates a payment gateway based on the provided type.
func NewPaymentGateway(gwType PaymentGatewayType) (PaymentGateway, error) {
    switch gwType {
    case PayPalGateway:
        return &PayPalGateway{}, nil
    case StripeGateway:
        return &StripeGateway{}, nil
    default:
        return nil, errors.New("unsupported payment gateway type")
    }
}

func main() {
    payPalGateway, _ := NewPaymentGateway(PayPalGateway)
    payPalGateway.ProcessPayment(100.00)

    stripeGateway, _ := NewPaymentGateway(StripeGateway)
    stripeGateway.ProcessPayment(150.50)
}

Enter fullscreen mode Exit fullscreen mode

In this example, we define the PaymentGateway interface as the shared contract for all payment gateways. We implement two concrete payment gateways, PayPalGateway and StripeGateway, each with its respective ProcessPayment method.

The NewPaymentGateway function acts as the factory method, creating payment gateways based on the provided type. It encapsulates the creation logic and returns the appropriate instance, allowing the client to interact with different payment gateways using a unified interface.

The client code demonstrates how to use the Factory Method Pattern to create and process payments through different gateways. By invoking NewPaymentGateway with the desired type, the client can obtain instances of specific payment gateways.

Conclusion 🥂

The Factory Method Pattern empowers flexible object creation, abstracting types from clients. With seamless integration, it fosters cleaner code and adapts to evolving needs. From payment gateways to varied objects, it's a design gem for crafting elegant software solutions. Embrace its versatility and elevate your coding prowess.

Top comments (1)

Collapse
 
ryuheechul profile image
Heechul Ryu

If anyone is new to iota, this article should be helpful, go101.org/article/constants-and-va...