refactored abstract-factory pattern
This commit is contained in:
		@@ -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