[go] Go 언어와 함께 사용할 수 있는 디자인 패턴 소개

Go 언어는 간결하고 효율적인 코드 작성을 지향하는 언어입니다. 이번에는 Go 언어와 함께 사용할 수 있는 디자인 패턴에 대해 알아보겠습니다.

Table of Contents

  1. 싱글톤 패턴 (Singleton Pattern)
  2. 빌더 패턴 (Builder Pattern)
  3. 팩토리 메서드 패턴 (Factory Method Pattern)
  4. 스트래티지 패턴 (Strategy Pattern)
  5. 데코레이터 패턴 (Decorator Pattern)

1. 싱글톤 패턴 (Singleton Pattern)

싱글톤 패턴은 애플리케이션 전역에서 오직 하나의 인스턴스를 생성하여 사용하는 패턴입니다. Go 언어에서는 sync 패키지의 Once 타입과 sync 패키지의 Mutex를 활용하여 싱글톤을 구현할 수 있습니다.

예제 코드:

package main

import (
	"sync"
)

type singleton struct {
}

var instance *singleton
var once sync.Once

func getInstance() *singleton {
	once.Do(func() {
		instance = &singleton{}
	})
	return instance
}

2. 빌더 패턴 (Builder Pattern)

빌더 패턴은 여러 개의 복잡한 단계를 거쳐야 하는 객체 생성을 단순화하는 패턴입니다. Go 언어에서는 생성자 함수를 사용하여 객체를 초기화하는 형태로 빌더 패턴을 구현할 수 있습니다.

예제 코드:

package main

type Person struct {
	name    string
	age     int
	address string
}

type PersonBuilder struct {
	person Person
}

func (pb *PersonBuilder) setName(name string) *PersonBuilder {
	pb.person.name = name
	return pb
}

func (pb *PersonBuilder) setAge(age int) *PersonBuilder {
	pb.person.age = age
	return pb
}

func (pb *PersonBuilder) setAddress(address string) *PersonBuilder {
	pb.person.address = address
	return pb
}

func (pb *PersonBuilder) build() Person {
	return pb.person
}

func main() {
	person := PersonBuilder{}.
		setName("John").
		setAge(30).
		setAddress("123 Main St").
		build()

	fmt.Println(person)
}

3. 팩토리 메서드 패턴 (Factory Method Pattern)

팩토리 메서드 패턴은 객체를 생성하는 인터페이스를 정의하고, 그 인터페이스를 구현한 클래스가 객체를 생성하는 패턴입니다. Go 언어에서는 인터페이스를 활용하여 팩토리 메서드 패턴을 구현할 수 있습니다.

예제 코드:

package main

import "fmt"

type Animal interface {
	makeSound()
}

type Dog struct {
}

func (d Dog) makeSound() {
	fmt.Println("멍멍!")
}

type Cat struct {
}

func (c Cat) makeSound() {
	fmt.Println("야옹~")
}

func getAnimal(animalType string) Animal {
	if animalType == "dog" {
		return Dog{}
	} else if animalType == "cat" {
		return Cat{}
	}
	return nil
}

func main() {
	animal1 := getAnimal("dog")
	animal1.makeSound()

	animal2 := getAnimal("cat")
	animal2.makeSound()
}

4. 스트래티지 패턴 (Strategy Pattern)

스트래티지 패턴은 알고리즘을 캡슐화하여 동적으로 알고리즘을 교체할 수 있도록 하는 패턴입니다. Go 언어에서는 인터페이스를 사용하여 스트래티지 패턴을 구현할 수 있습니다.

예제 코드:

package main

import "fmt"

type PaymentStrategy interface {
	pay(amount float64) string
}

type CreditCard struct{}

func (c CreditCard) pay(amount float64) string {
	return fmt.Sprintf("신용카드로 %.2f원 결제가 완료되었습니다.", amount)
}

type Cash struct{}

func (c Cash) pay(amount float64) string {
	return fmt.Sprintf("%.2f원을 현금으로 결제했습니다.", amount)
}

type PaymentContext struct {
	strategy PaymentStrategy
}

func (pc *PaymentContext) pay(amount float64) string {
	return pc.strategy.pay(amount)
}

func main() {
	cardPayment := PaymentContext{CreditCard{}}
	fmt.Println(cardPayment.pay(10000.0))

	cashPayment := PaymentContext{Cash{}}
	fmt.Println(cashPayment.pay(5000.0))
}

5. 데코레이터 패턴 (Decorator Pattern)

데코레이터 패턴은 객체에 추가적인 기능을 동적으로 부여할 수 있는 패턴입니다. Go 언어에서는 함수를 매개변수로 받는 형태로 데코레이터 패턴을 구현할 수 있습니다.

예제 코드:

package main

import "fmt"

type Beverage interface {
	cost() int
}

type Espresso struct{}

func (e Espresso) cost() int {
	return 2000
}

type Milk struct {
	beverage Beverage
}

func (m Milk) cost() int {
	return m.beverage.cost() + 500
}

func main() {
	espresso := Espresso{}
	fmt.Println(espresso.cost())

	milkedEspresso := Milk{espresso}
	fmt.Println(milkedEspresso.cost())
}

디자인 패턴은 코드의 품질을 향상시키고 유지보수를 용이하게 합니다. Go 언어를 사용하면서 이러한 디자인 패턴을 익혀두면 효율적인 개발이 가능할 것입니다.