awesome-patterns/creational/abstract_factory.md
2021-07-08 23:59:13 -03:00

1.6 KiB

Abstract Factory Pattern

Provide an interface for creating families of related or dependent objects without specifying their concrete classes

Implementation

const (
    CAR  = 1
    LuxuryCarType = 1
    FamilyCarType = 2
)

type Car interface {
    NumDoors() int
}

func CreateVehicleFactory(v int) (VehicleFactory, error) {
    switch v {
    case CAR:
        return new(CarFactory), nil
    default:
        return nil, errors.New(fmt.Sprintf("Factory of type %d not exist\n", v))
    }
}

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, errors.New(fmt.Sprintf("Vehicle of type %d not exist\n", v))
    }
}

type FamilyCar struct{}

func (*FamilyCar) NumDoors() int {
    return 5
}

func (*FamilyCar) NumWheels() int {
    return 4
}

func (*FamilyCar) NumSeats() int {
    return 5
}

type LuxuryCar struct{}

func (*LuxuryCar) NumDoors() int {
    return 4
}

func (*LuxuryCar) NumWheels() int {
    return 4
}

func (*LuxuryCar) NumSeats() int {
    return 5
}

type Vehicle interface {
    NumWheels() int
    NumSeats() int
}

type VehicleFactory interface {
    NewVehicle(v int) (Vehicle, error)
}

Usage

carFactory, err := CreateVehicleFactory(CAR)
if err != nil {
	panic(err)
}

luxuryCar, err := carFactory.NewVehicle(LuxuryCarType)
if err != nil {
	panic(err)
}

car, ok := luxuryCar.(Car)
if !ok {
	panic(err)
}

fmt.Println(luxuryCar.NumWheels(), luxuryCar.NumSeats(), car.NumDoors())