이 패턴은 불필요한 의존성을 없애고 변경,확장에 좋은 패턴으로 개방-폐쇄 원칙을 지키고 있다. 객체를 생성하는 클래스를 팩토리라고 부른다.
객체를 생성하기 위한 인터페이스를 정의함으로써 실제 인스턴스를 만드는 것을 서브 클래스로 넘기는 것으로 인터페이스 바탕의 프로그래밍을 할 수 있게 되며, 그 결과 유연성과 확장성을 얻을 수 있게 된다.
또한 생성 코드를 전부 한 객체 또는 메소드에 집어 넣어 코드의 중복처리를 막아 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)
}
다만 단점으로는 클래스가 많아져 각 계층이 많아질 수 있다는 점이다. 하지만 서브클래스에게 생성을 위임함으로 의존성을 제거하여 클래스 변경에 따른 다른 클래스로의 영향을 없애고 코드 제어에 원할한 장점이 있는 패턴이다.