From c253feefc294875680a758c1cddb0facf9cb441c Mon Sep 17 00:00:00 2001 From: ismayilmalik Date: Sat, 9 Mar 2019 23:38:10 +0300 Subject: [PATCH] refactored abstract-factory pattern --- .gitignore | 2 + .../abstract_factory/abstract_factory.go | 95 ++----------------- .../abstract_factory/abstract_factory_test.go | 41 ++++++++ creational/abstract_factory/bus.go | 17 ++++ creational/abstract_factory/bus_factory.go | 25 +++++ creational/abstract_factory/car.go | 18 ++++ creational/abstract_factory/car_factory.go | 25 +++++ creational/abstract_factory/city_tour_bus.go | 27 ++++++ creational/abstract_factory/micro_bus.go | 27 ++++++ creational/abstract_factory/ofroad_car.go | 27 ++++++ creational/abstract_factory/sport_car.go | 27 ++++++ creational/abstract_factory/vehicle.go | 15 +++ .../abstract_factory/vehicle_factory.go | 10 ++ 13 files changed, 268 insertions(+), 88 deletions(-) create mode 100644 creational/abstract_factory/abstract_factory_test.go create mode 100644 creational/abstract_factory/bus.go create mode 100644 creational/abstract_factory/bus_factory.go create mode 100644 creational/abstract_factory/car.go create mode 100644 creational/abstract_factory/car_factory.go create mode 100644 creational/abstract_factory/city_tour_bus.go create mode 100644 creational/abstract_factory/micro_bus.go create mode 100644 creational/abstract_factory/ofroad_car.go create mode 100644 creational/abstract_factory/sport_car.go create mode 100644 creational/abstract_factory/vehicle.go create mode 100644 creational/abstract_factory/vehicle_factory.go diff --git a/.gitignore b/.gitignore index 0b61b15..132c9e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ # Binaries for programs and plugins *.exe +fl +main.go \ No newline at end of file diff --git a/creational/abstract_factory/abstract_factory.go b/creational/abstract_factory/abstract_factory.go index a73e25b..5568572 100644 --- a/creational/abstract_factory/abstract_factory.go +++ b/creational/abstract_factory/abstract_factory.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)) } } \ No newline at end of file diff --git a/creational/abstract_factory/abstract_factory_test.go b/creational/abstract_factory/abstract_factory_test.go new file mode 100644 index 0000000..b9a7926 --- /dev/null +++ b/creational/abstract_factory/abstract_factory_test.go @@ -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.") + } +} \ No newline at end of file diff --git a/creational/abstract_factory/bus.go b/creational/abstract_factory/bus.go new file mode 100644 index 0000000..53c8271 --- /dev/null +++ b/creational/abstract_factory/bus.go @@ -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 +} \ No newline at end of file diff --git a/creational/abstract_factory/bus_factory.go b/creational/abstract_factory/bus_factory.go new file mode 100644 index 0000000..a108eb8 --- /dev/null +++ b/creational/abstract_factory/bus_factory.go @@ -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)) + } +} diff --git a/creational/abstract_factory/car.go b/creational/abstract_factory/car.go new file mode 100644 index 0000000..91e7399 --- /dev/null +++ b/creational/abstract_factory/car.go @@ -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 +} diff --git a/creational/abstract_factory/car_factory.go b/creational/abstract_factory/car_factory.go new file mode 100644 index 0000000..a194c46 --- /dev/null +++ b/creational/abstract_factory/car_factory.go @@ -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)) + } +} diff --git a/creational/abstract_factory/city_tour_bus.go b/creational/abstract_factory/city_tour_bus.go new file mode 100644 index 0000000..1ea6745 --- /dev/null +++ b/creational/abstract_factory/city_tour_bus.go @@ -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 +} \ No newline at end of file diff --git a/creational/abstract_factory/micro_bus.go b/creational/abstract_factory/micro_bus.go new file mode 100644 index 0000000..76d134f --- /dev/null +++ b/creational/abstract_factory/micro_bus.go @@ -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 +} \ No newline at end of file diff --git a/creational/abstract_factory/ofroad_car.go b/creational/abstract_factory/ofroad_car.go new file mode 100644 index 0000000..29891ff --- /dev/null +++ b/creational/abstract_factory/ofroad_car.go @@ -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 +} \ No newline at end of file diff --git a/creational/abstract_factory/sport_car.go b/creational/abstract_factory/sport_car.go new file mode 100644 index 0000000..364d2bd --- /dev/null +++ b/creational/abstract_factory/sport_car.go @@ -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 +} \ No newline at end of file diff --git a/creational/abstract_factory/vehicle.go b/creational/abstract_factory/vehicle.go new file mode 100644 index 0000000..70395d0 --- /dev/null +++ b/creational/abstract_factory/vehicle.go @@ -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 +} \ No newline at end of file diff --git a/creational/abstract_factory/vehicle_factory.go b/creational/abstract_factory/vehicle_factory.go new file mode 100644 index 0000000..c3ab14c --- /dev/null +++ b/creational/abstract_factory/vehicle_factory.go @@ -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) +} \ No newline at end of file