refactored abstract-factory pattern

This commit is contained in:
ismayilmalik 2019-03-09 23:38:10 +03:00
parent 08c61fdfc8
commit c253feefc2
13 changed files with 268 additions and 88 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
# Binaries for programs and plugins # Binaries for programs and plugins
*.exe *.exe
fl
main.go

View File

@ -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))
} }
} }

View 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.")
}
}

View 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
}

View 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))
}
}

View 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
}

View 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))
}
}

View 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
}

View 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
}

View 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
}

View 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
}

View 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
}

View 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)
}