이 패턴은 불필요한 의존성을 없애고 변경,확장에 좋은 패턴으로 개방-폐쇄 원칙을 지키고 있다. 객체를 생성하는 클래스를 팩토리라고 부른다.

객체를 생성하기 위한 인터페이스를 정의함으로써 실제 인스턴스를 만드는 것을 서브 클래스로 넘기는 것으로 인터페이스 바탕의 프로그래밍을 할 수 있게 되며, 그 결과 유연성과 확장성을 얻을 수 있게 된다.

또한 생성 코드를 전부 한 객체 또는 메소드에 집어 넣어 코드의 중복처리를 막아 DIY원칙을 지키며 나중에 관리 또한 한곳에서 하기 때문에 응집성을 높혀준다. 또한 객체 생성 코드를 아무 곳에서 흩어져 관리하는 것보다 안전해진다.

package factory

import (
	"errors"
	"fmt"
)

/*
Prototype Factory
*/
type PaymentMethod interface {
	Pay(amount float32) string
}

const (
	Cash      = 1
	DebitCard = 2
)

type CashPM struct{}

func (c *CashPM) Pay(amount float32) string {
	return fmt.Sprintf("%0.2f payed using cash\\n", amount)
}

type DebitCardPM struct{}

func (d *DebitCardPM) Pay(amount float32) string {
	return fmt.Sprintf("%#0.2f payed using debit card\\n", amount)
}

func GetPaymentMethod(m int) (PaymentMethod, error) {
	switch m {
	case Cash:
		return new(CashPM), nil
	case DebitCard:
		return new(DebitCardPM), nil
	default:
		return nil, errors.New(fmt.Sprintf("Payment method %d not recognized\\n", m))
	}
}

/*
Factory Geneator
*/
type Employee struct {
	position string
	salary   int
	name     string
}

//closer
func NewEmployeeFactory(position string, salary int) func(name string) *Employee {
	return func(name string) *Employee {
		return &Employee{position, salary, name}
	}
}

func main() {
	developerFactory := NewEmployeeFactory("developer", 60000)
	managerFactory := NewEmployeeFactory("manager", 50000)

	developer := developerFactory("Song")
	manager := managerFactory("JC")

	fmt.Printf("신규 취업자: ", developer, manager)
}

다만 단점으로는 클래스가 많아져 각 계층이 많아질 수 있다는 점이다. 하지만 서브클래스에게 생성을 위임함으로 의존성을 제거하여 클래스 변경에 따른 다른 클래스로의 영향을 없애고 코드 제어에 원할한 장점이 있는 패턴이다.