반응형
SMALL
추상 팩토리(Abstract Factory)
추상 팩토리 디자인 패턴은 인터페이스를 통해 사용되는 더 큰(그리고 더 복잡한) 복합 객체를 달성하기 위한 새로운 그룹화 계층입니다. 패밀리에 객체를 그룹화하고 패밀리를 그룹화하는 아이디어는 서로 교환할 수 있고 더 쉽게 성장할 수 있는 대규모 공장을 갖는 것입니다. 개발 초기 단계에서는 코드를 시작하기 위해 모든 구체적인 구현이 완료될 때까지 기다리는 것보다 공장 및 추상 공장과 함께 작업하는 것이 더 쉽습니다. 또한 특정 필드에 대한 개체의 인벤토리가 매우 크고 쉽게 패밀리로 그룹화될 수 있다는 것을 알지 못하는 한 처음부터 추상 팩토리를 작성하지 않습니다. 개체 수가 너무 증가하여 개체 수를 모두 얻기 위해 고유한 점을 만드는 것이 유일한 방법일 때 관련 개체 패밀리를 그룹화하는 것이 매우 편리합니다.
package abstractfactory
type Vehicle interface {
NumWheels() int
NumSeats() int
}
package abstractfactory
import "fmt"
const (
CarFactoryType = 1
MotorbikeFactoryType = 2
)
type VehicleFactory interface {
NewVehicle(v int) (Vehicle, error)
}
func BuildFactory(f int) (VehicleFactory, error) {
switch f {
case CarFactoryType:
return new(CarFactory), nil
case MotorbikeFactoryType:
return new(MotorbikeFactory), nil
default:
return nil, fmt.Errorf("factory with id %d not recognized", f)
}
}
package abstractfactory
type Motorbike interface {
GetMotorbikeType() int
}
type SportMotorbike struct{}
func (s *SportMotorbike) NumWheels() int {
return 2
}
func (s *SportMotorbike) NumSeats() int {
return 1
}
func (s *SportMotorbike) GetMotorbikeType() int {
return SportMotorbikeType
}
type CruiseMotorbike struct{}
func (c *CruiseMotorbike) NumWheels() int {
return 2
}
func (c *CruiseMotorbike) NumSeats() int {
return 2
}
func (c *CruiseMotorbike) GetMotorbikeType() int {
return CruiseMotorbikeType
}
package abstractfactory
import "fmt"
const (
SportMotorbikeType = 1
CruiseMotorbikeType = 2
)
type MotorbikeFactory struct{}
func (m *MotorbikeFactory) NewVehicle(v int) (Vehicle, error) {
switch v {
case SportMotorbikeType:
return new(SportMotorbike), nil
case CruiseMotorbikeType:
return new(CruiseMotorbike), nil
default:
return nil, fmt.Errorf("vehicle of type %d not recognized", v)
}
}
package abstractfactory
type Car interface {
NumDoors() int
}
type LuxuryCar struct{}
func (*LuxuryCar) NumDoors() int {
return 4
}
func (*LuxuryCar) NumWheels() int {
return 4
}
func (*LuxuryCar) NumSeats() int {
return 5
}
type FamilyCar struct{}
func (*FamilyCar) NumDoors() int {
return 5
}
func (*FamilyCar) NumWheels() int {
return 4
}
func (*FamilyCar) NumSeats() int {
return 5
}
package abstractfactory
import "fmt"
const (
LuxuryCarType = 1
FamilyCarType = 2
)
type CarFactory struct{}
func (c *CarFactory) NewVehicle(v int) (Vehicle, error) {
switch v {
case LuxuryCarType:
return new(LuxuryCar), nil
case FamilyCarType:
return new(FamilyCar), nil
default:
return nil, fmt.Errorf("vehicle of type %d not recognized", v)
}
}
Test Code
package abstractfactory
import "testing"
func TestMotorbikeFactory(t *testing.T) {
motorbikeFactory, err := BuildFactory(MotorbikeFactoryType)
if err != nil {
t.Fatal(err)
}
sportMotorbikeVehicle, err := motorbikeFactory.NewVehicle(SportMotorbikeType)
if err != nil {
t.Fatal(err)
}
t.Logf("motorbike vehicle has %d wheels", sportMotorbikeVehicle.NumWheels())
t.Logf("motorbike vehicle has %d seats", sportMotorbikeVehicle.NumSeats())
sportMotorbike, ok := sportMotorbikeVehicle.(Motorbike)
if !ok {
t.Fatal("struct assertion has failed")
}
t.Logf("sport motorbike has type %d", sportMotorbike.GetMotorbikeType())
cruiseMotorbikeVehicle, err := motorbikeFactory.NewVehicle(CruiseMotorbikeType)
if err != nil {
t.Fatal(err)
}
t.Logf("motorbike vehicle has %d wheels", cruiseMotorbikeVehicle.NumWheels())
t.Logf("motorbike vehicle has %d seats", sportMotorbikeVehicle.NumSeats())
cruiseMotorbike, ok := cruiseMotorbikeVehicle.(Motorbike)
if !ok {
t.Fatal("struct assertion has failed")
}
t.Logf("sport motorbike has type %d", cruiseMotorbike.GetMotorbikeType())
}
func TestCarFactory(t *testing.T) {
carFactory, err := BuildFactory(CarFactoryType)
if err != nil {
t.Fatal(err)
}
luxuryCarVehicle, err := carFactory.NewVehicle(LuxuryCarType)
if err != nil {
t.Fatal(err)
}
t.Logf("car vehicle has %d wheels\n", luxuryCarVehicle.NumWheels())
t.Logf("car vehicle has %d seats\n", luxuryCarVehicle.NumSeats())
luxuryCar, ok := luxuryCarVehicle.(Car)
if !ok {
t.Fatal("struct assertion has failed")
}
t.Logf("luxury car has %d doors", luxuryCar.NumDoors())
familyCarVehicle, err := carFactory.NewVehicle(FamilyCarType)
if err != nil {
t.Fatal(err)
}
t.Logf("car vehicle has %d wheels", familyCarVehicle.NumWheels())
t.Logf("car vehicle has %d seats", luxuryCarVehicle.NumSeats())
familyCar, ok := familyCarVehicle.(Car)
if !ok {
t.Fatal("struct assertion has failed")
}
t.Logf("family car has %d doors", familyCar.NumDoors())
}
func TestFactoryNonExistent(t *testing.T) {
_, err := BuildFactory(3)
if err == nil {
t.Error("a factory with ID 3 must return an error")
}
t.Log("LOG:", err)
}
프로토타입(Prototype)
프로토타입의 목적은 컴파일 시 이미 생성되었지만 런타임에 원하는 횟수만큼 복제할 수 있는 개체 또는 개체 집합을 갖는 것입니다. 이 기능은 웹 페이지에 등록한 지 얼마 되지 않은 사용자의 기본 템플릿이나 일부 서비스의 기본 요금제로 유용합니다. 이 패턴과 Builder 패턴의 주요 차이점은 객체가 런타임에 빌드되지 않고 사용자를 위해 복제된다는 것입니다. 프로토타입을 사용하여 정보를 저장하는 캐시와 같은 솔루션을 구축할 수도 있습니다.
package prototype
import (
"errors"
"fmt"
)
const (
White = 1
Black = 2
Blue = 3
)
var whitePrototype *Shirt = &Shirt{
Price: 15.00,
SKU: "empty",
Color: White,
}
var blackPrototype *Shirt = &Shirt{
Price: 16.00,
SKU: "empty",
Color: Black,
}
var bluePrototype *Shirt = &Shirt{
Price: 17.00,
SKU: "empty",
Color: Blue,
}
type ShirtCloner interface {
GetClone(s int) (ItemInfoGetter, error)
}
func GetShirtCloner() ShirtCloner {
return new(ShirtCache)
}
type ShirtCache struct{}
func (s *ShirtCache) GetClone(m int) (ItemInfoGetter, error) {
switch m {
case White:
newItem := *whitePrototype
return &newItem, nil
case Black:
newItem := *blackPrototype
return &newItem, nil
case Blue:
newItem := *bluePrototype
return &newItem, nil
default:
return nil, errors.New("Shirt model not recognized")
}
}
type ItemInfoGetter interface {
GetInfo() string
}
type ShirtColor byte
type Shirt struct {
Price float32
SKU string
Color ShirtColor
}
func (s *Shirt) GetInfo() string {
return fmt.Sprintf("Shirt with SKU '%s' and Color id %d that costs %f\n", s.SKU, s.Color, s.Price)
}
func (s *Shirt) GetPrice() float32 {
return s.Price
}
프로토타입 패턴은 캐시 및 기본 개체를 구축하는 강력한 도구입니다.
반응형
LIST
'Go' 카테고리의 다른 글
[Design Pattern] 프록시(Proxy), 데코레이터(Decorator), 퍼사드(Facade) (0) | 2022.11.24 |
---|---|
[Design Pattern] 합성(Composite), 어댑터(Adapter), 브릿지(Bridge) 패턴 (0) | 2022.11.23 |
[Design Pattern] 싱글톤(Singleton), 빌더(Builder), 팩토리 메소드(Factory Method) 패턴 (0) | 2022.11.21 |
Go의 고루틴과 채널 (0) | 2022.01.10 |
Go의 메소드와 인터페이스 (0) | 2022.01.07 |