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
|
||||
*.exe
|
||||
fl
|
||||
main.go
|
@ -5,98 +5,17 @@ import (
|
||||
"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 (
|
||||
CAR = 1
|
||||
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) {
|
||||
switch vfType {
|
||||
case CAR:
|
||||
@ -104,6 +23,6 @@ func CreateVehicleFactory(vfType int) (VehicleFactory, error) {
|
||||
case BUS:
|
||||
return new(BusFactory), nil
|
||||
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