refactored abstract-factory pattern
This commit is contained in:
parent
08c61fdfc8
commit
c253feefc2
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
# Binaries for programs and plugins
|
# Binaries for programs and plugins
|
||||||
*.exe
|
*.exe
|
||||||
|
fl
|
||||||
|
main.go
|
@ -5,98 +5,17 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
//sub factory abstractions
|
|
||||||
type VehicleFactory interface {
|
|
||||||
Create(int) (Vehiche, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type CarFactory struct{}
|
|
||||||
func (f *CarFactory) Create(vType int) (Vehiche, error) {
|
|
||||||
switch vType {
|
|
||||||
case OFFROADER_CAR:
|
|
||||||
return new(Offroader), nil
|
|
||||||
case SPORT_CAR:
|
|
||||||
return new(Sportcar), nill
|
|
||||||
default:
|
|
||||||
return nil, errors.New(fmt.Sprintf("Unsupported car vehicle type:%d", vType))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type BusFactory struct {}
|
|
||||||
func(f *BusFactory) Create(vType int)(Vehiche, error) {
|
|
||||||
switch vType {
|
|
||||||
case CITY_TOUR_BUS:
|
|
||||||
return new(CityTourBus), nil
|
|
||||||
case SIMPLE_BUS:
|
|
||||||
return new(SimpleBus), nil
|
|
||||||
default:
|
|
||||||
return nil, errors.New(fmt.Sprintf("Unsupported bus vehicle type:%d", vType))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//object families............
|
|
||||||
type Vehiche interface {
|
|
||||||
WheelCount() int
|
|
||||||
}
|
|
||||||
|
|
||||||
//Car
|
|
||||||
const (
|
|
||||||
OFFROADER_CAR = 1
|
|
||||||
SPORT_CAR = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
type Car interface {
|
|
||||||
DoorCount() int
|
|
||||||
}
|
|
||||||
|
|
||||||
type Offroader struct{}
|
|
||||||
func (c Offroader) WheelCount() int {
|
|
||||||
return 4
|
|
||||||
}
|
|
||||||
func (c Offroader) DoorCount() int {
|
|
||||||
return 4
|
|
||||||
}
|
|
||||||
|
|
||||||
type Sportcar struct{}
|
|
||||||
func (c Sportcar) WheelCount() int {
|
|
||||||
return 4
|
|
||||||
}
|
|
||||||
func (c Sportcar) DoorCount() int {
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
|
|
||||||
//Bus..................
|
|
||||||
const (
|
|
||||||
SIMPLE_BUS = 1
|
|
||||||
CITY_TOUR_BUS = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
type Bus interface {
|
|
||||||
FloorCount() int
|
|
||||||
}
|
|
||||||
|
|
||||||
type CityTourBus struct{}
|
|
||||||
func (c CityTourBus) WheelCount() int {
|
|
||||||
return 6
|
|
||||||
}
|
|
||||||
func (c CityTourBus) FloorCount() int {
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
|
|
||||||
type SimpleBus struct{}
|
|
||||||
func (c SimpleBus) WheelCount() int {
|
|
||||||
return 4
|
|
||||||
}
|
|
||||||
func (c SimpleBus) FloorCount() int {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
//super factory
|
|
||||||
const (
|
const (
|
||||||
CAR = 1
|
CAR = 1
|
||||||
BUS = 2
|
BUS = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CreateVehicleFactory function makes subfamily factories of Vehicle
|
||||||
|
* family. The goal is to split object family creation complexity
|
||||||
|
* into small blocks in order to make it easy to read and maintain.
|
||||||
|
* It basicaly delegates subfamily object creations to subfamily factories.
|
||||||
|
*/
|
||||||
func CreateVehicleFactory(vfType int) (VehicleFactory, error) {
|
func CreateVehicleFactory(vfType int) (VehicleFactory, error) {
|
||||||
switch vfType {
|
switch vfType {
|
||||||
case CAR:
|
case CAR:
|
||||||
@ -104,6 +23,6 @@ func CreateVehicleFactory(vfType int) (VehicleFactory, error) {
|
|||||||
case BUS:
|
case BUS:
|
||||||
return new(BusFactory), nil
|
return new(BusFactory), nil
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("Unrecognized factory type:%d", vfType)
|
return nil, errors.New(fmt.Sprintf("Unrecognized factory type:%d", vfType))
|
||||||
}
|
}
|
||||||
}
|
}
|
41
creational/abstract_factory/abstract_factory_test.go
Normal file
41
creational/abstract_factory/abstract_factory_test.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package abstract_factory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCarFactory(t *testing.T) {
|
||||||
|
|
||||||
|
carFactory, err := CreateVehicleFactory(CAR)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sportCarVehicle, err := carFactory.NewVehicle(SPORT_CAR)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sc, ok := sportCarVehicle.(Car)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("Struct assertion failed.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBusFactory(t *testing.T) {
|
||||||
|
|
||||||
|
busFactory, err := CreateVehicleFactory(BUS)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cistyTourBusVehicle, err := busFactory.NewVehicle(CITY_TOUR_BUS)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := cistyTourBusVehicle.(Bus)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("Struct assertion failed.")
|
||||||
|
}
|
||||||
|
}
|
17
creational/abstract_factory/bus.go
Normal file
17
creational/abstract_factory/bus.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package abstract_factory
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bus is also a subfamliy of Vehicle
|
||||||
|
* But it has some specific properties
|
||||||
|
* thus based on these properties has some variations
|
||||||
|
* Therefore it need it's own factory
|
||||||
|
*/
|
||||||
|
type Bus interface {
|
||||||
|
|
||||||
|
Vehiche
|
||||||
|
|
||||||
|
// As some buses can have multiple floors
|
||||||
|
// let's consider this is a big difference from
|
||||||
|
// other vehicles
|
||||||
|
FloorCount() int
|
||||||
|
}
|
25
creational/abstract_factory/bus_factory.go
Normal file
25
creational/abstract_factory/bus_factory.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package abstract_factory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MICRO_BUS = 1
|
||||||
|
CITY_TOUR_BUS = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type BusFactory struct {}
|
||||||
|
|
||||||
|
// Creates vehicles which is member of Bus subfamily group
|
||||||
|
func(f *BusFactory) NewVehicle(busType int)(Vehiche, error) {
|
||||||
|
switch busType {
|
||||||
|
case CITY_TOUR_BUS:
|
||||||
|
return new(CityTourBus), nil
|
||||||
|
case MICRO_BUS:
|
||||||
|
return new(MicroBus), nil
|
||||||
|
default:
|
||||||
|
return nil, errors.New(fmt.Sprintf("Unsupported bus vehicle type:%d", busType))
|
||||||
|
}
|
||||||
|
}
|
18
creational/abstract_factory/car.go
Normal file
18
creational/abstract_factory/car.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package abstract_factory
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Car is a subfamliy of Vehicle
|
||||||
|
* But it has some specific properties
|
||||||
|
* thus based on these properties has some variations
|
||||||
|
* Therefore it need it's own factory
|
||||||
|
*/
|
||||||
|
type Car interface {
|
||||||
|
|
||||||
|
// Just embeding Vehicle interface
|
||||||
|
// in order to extend from it
|
||||||
|
Vehiche
|
||||||
|
|
||||||
|
// Let's assume this property belongs to
|
||||||
|
// only Car type vehicles
|
||||||
|
HasElectricEngine() bool
|
||||||
|
}
|
25
creational/abstract_factory/car_factory.go
Normal file
25
creational/abstract_factory/car_factory.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package abstract_factory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
OFFROADER_CAR = 1
|
||||||
|
SPORT_CAR = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
type CarFactory struct{}
|
||||||
|
|
||||||
|
// Creates vehicles which is member of Car subfamily group
|
||||||
|
func (f *CarFactory) NewVehicle(carType int) (Vehiche, error) {
|
||||||
|
switch carType {
|
||||||
|
case OFFROADER_CAR:
|
||||||
|
return new(Offroader), nil
|
||||||
|
case SPORT_CAR:
|
||||||
|
return new(Sportcar), nil
|
||||||
|
default:
|
||||||
|
return nil, errors.New(fmt.Sprintf("Unsupported car vehicle type:%d", carType))
|
||||||
|
}
|
||||||
|
}
|
27
creational/abstract_factory/city_tour_bus.go
Normal file
27
creational/abstract_factory/city_tour_bus.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package abstract_factory
|
||||||
|
|
||||||
|
// A group of Bus family
|
||||||
|
type CityTourBus struct{
|
||||||
|
wheels int
|
||||||
|
doors int
|
||||||
|
speed int
|
||||||
|
floorCount int
|
||||||
|
|
||||||
|
// Some CityTourBus specific properties
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CityTourBus) FloorCount() int {
|
||||||
|
return c.floorCount
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CityTourBus) WheelCount() int {
|
||||||
|
return c.wheels
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CityTourBus) NumberOfDoors() int {
|
||||||
|
return c.doors
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c CityTourBus) Speed() int {
|
||||||
|
return c.speed
|
||||||
|
}
|
27
creational/abstract_factory/micro_bus.go
Normal file
27
creational/abstract_factory/micro_bus.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package abstract_factory
|
||||||
|
|
||||||
|
// A group of Bus family
|
||||||
|
type MicroBus struct{
|
||||||
|
wheels int
|
||||||
|
doors int
|
||||||
|
speed int
|
||||||
|
floorCount int
|
||||||
|
|
||||||
|
// Some CityTourBus specific properties
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c MicroBus) FloorCount() int {
|
||||||
|
return c.floorCount
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c MicroBus) WheelCount() int {
|
||||||
|
return c.wheels
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c MicroBus) NumberOfDoors() int {
|
||||||
|
return c.doors
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c MicroBus) Speed() int {
|
||||||
|
return c.speed
|
||||||
|
}
|
27
creational/abstract_factory/ofroad_car.go
Normal file
27
creational/abstract_factory/ofroad_car.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package abstract_factory
|
||||||
|
|
||||||
|
// A group of Car family
|
||||||
|
type Offroader struct{
|
||||||
|
wheels int
|
||||||
|
doors int
|
||||||
|
speed int
|
||||||
|
hasElectricEngine bool
|
||||||
|
|
||||||
|
// Some offroader specific properties
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Offroader) WheelCount() int {
|
||||||
|
return c.wheels
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Offroader) NumberOfDoors() int {
|
||||||
|
return c.doors
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Offroader) Speed() int {
|
||||||
|
return c.speed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Offroader) HasElectricEngine() bool {
|
||||||
|
return c.hasElectricEngine
|
||||||
|
}
|
27
creational/abstract_factory/sport_car.go
Normal file
27
creational/abstract_factory/sport_car.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package abstract_factory
|
||||||
|
|
||||||
|
// A group of Car family
|
||||||
|
type Sportcar struct{
|
||||||
|
wheels int
|
||||||
|
doors int
|
||||||
|
speed int
|
||||||
|
hasElectricEngine bool
|
||||||
|
|
||||||
|
// Some sportcar specific properties
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Sportcar) WheelCount() int {
|
||||||
|
return c.wheels
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Sportcar) NumberOfDoors() int {
|
||||||
|
return c.doors
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Sportcar) Speed() int {
|
||||||
|
return c.speed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c Sportcar) HasElectricEngine() bool {
|
||||||
|
return c.hasElectricEngine
|
||||||
|
}
|
15
creational/abstract_factory/vehicle.go
Normal file
15
creational/abstract_factory/vehicle.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package abstract_factory
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vehicle is root abstractions for the family
|
||||||
|
* It contains very common behavior for the
|
||||||
|
* family tree
|
||||||
|
*/
|
||||||
|
type Vehiche interface {
|
||||||
|
|
||||||
|
WheelCount() int
|
||||||
|
|
||||||
|
NumberOfDoors() int
|
||||||
|
|
||||||
|
Speed() int
|
||||||
|
}
|
10
creational/abstract_factory/vehicle_factory.go
Normal file
10
creational/abstract_factory/vehicle_factory.go
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
package abstract_factory
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is abstract factory for Vehicle family groups
|
||||||
|
* Each new family group factory should implement
|
||||||
|
* this interface
|
||||||
|
*/
|
||||||
|
type VehicleFactory interface {
|
||||||
|
NewVehicle(int) (Vehiche, error)
|
||||||
|
}
|
Reference in New Issue
Block a user