Применение абстрактного шаблона проектирования фабрики в переполнении стека

У меня есть программа, где пользователь вводит операции самолета. Пользователь может выбрать столько операций (удержание, прямой, посадка и т. Д.), Сколько ему нужно. Пользователь может рассчитать необходимый расход топлива с помощью операции 5.

Я решил применить абстрактный шаблон проектирования фабрики к своему коду. Вот текущая версия кода без шаблона применяется:

#include <iostream>
#include <stdio.h>
using namespace std;

class FlyingMode {

protected:

float time, fuel_rate, start, end, pace, distance;
float total;

public:
FlyingMode(float _time=0, float _fuel_rate=0, float _start=0,
float _end=0, float _pace=0, float _distance=0){

time = _time;
fuel_rate = _fuel_rate;
start = _start;
end = _end;
pace = _pace;
distance = _distance;
total = 0;
}

virtual ~FlyingMode() {}

virtual float calcFuel(){
return 0;
}
};

class Holding: public FlyingMode{

public:
Holding(float _time=0, float _fuel_rate=0, float _start=0,
float _end=0, float _pace=0, float _distance=0)
:FlyingMode(_time, _fuel_rate, _start, _end, _pace, _distance) { }

float calcFuel(){
total = (time * fuel_rate * 60);
return total;
}
};

class Raising: public FlyingMode{

public:
Raising(float _time=0, float _fuel_rate=0, float _start=0,
float _end=0, float _pace=0, float _distance=0)
:FlyingMode(_time, _fuel_rate, _start, _end, _pace, _distance) { }

float calcFuel (){
if(start < end && pace != 0 ){
float rising_time = (end - start)/pace;
total = rising_time * fuel_rate;
return total;
}else{
return 0;
}
}
};

class Landing: public FlyingMode{

public:
Landing(float _time=0, float _fuel_rate=0, float _start=0,
float _end=0, float _pace=0, float _distance=0)
:FlyingMode(_time, _fuel_rate, _start, _end, _pace, _distance) { }

float calcFuel (){

if(start > end && pace != 0 ){
float landing_time = (start - end)/pace;
total =  landing_time * fuel_rate;
return total;
}else{
return 0;
}

}
};

class Straight: public FlyingMode{

public:
Straight(float _time=0, float _fuel_rate=0, float _start=0,
float _end=0, float _pace=0, float _distance=0)
:FlyingMode(_time, _fuel_rate, _start, _end, _pace, _distance) { }

float calcFuel (){

if(distance != 0 || pace != 0 ){
float straight_time = distance/pace;
total = straight_time * fuel_rate;
return total;
}else{
return 0;
}
}
};

// Main function for the program
int main( ){

char op = 's';
float time=0, fuel_rate=0, start=0, end=0, pace=0, distance=0;
float total = 0;

while(op != 'x') {
FlyingMode *mode;
Holding hold;
Raising raise;
Landing land;
Straight straight;

float hold_result, raise_result, land_result, str_result;

cout << "Please select an operation: " << endl;
cout << "1 ---> Holding flight" << endl;
cout << "2 ---> Raising" << endl;
cout << "3 ---> Landing " << endl;
cout << "4 ---> Straight " << endl;
cout << "5 ---> Calculate total fuel consumption" << endl;
cout << "x ---> Exit " << endl;

cin >> op;

switch(op){
case '1':
cout << "Holding time (minutes): ";
cin >> time;
cout << "Fuel rate (kg/sec): ";
cin >> fuel_rate;

//call holding fuel
hold = Holding(time, fuel_rate, 0, 0, 0, 0);
mode = &hold;

hold_result = mode -> calcFuel();
total += hold_result;
break;
case '2':
cout << "Enter starting altitude of raising (meters): ";
cin >> start;
cout << "Enter ending altitude of raising (meters):";
cin >> end;
cout << "Enter raising pace (meter/sec): ";
cin >> pace;
cout << "Fuel rate (kg/sec): ";
cin >> fuel_rate;

raise = Raising(0, fuel_rate, start, end, pace, 0);
//call raising fuel
mode = &raise;

raise_result = mode -> calcFuel();
total += raise_result;
break;
case '3':
cout << "Enter starting altitude of landing (meters): ";
cin >> start;
cout << "Enter ending altitude of landing (meters):  ";
cin >> end;
cout << "Enter landing pace (meter/sec):  ";
cin >> pace;
cout << "Fuel rate (kg/sec):  ";
cin >> fuel_rate;

land = Landing(0, fuel_rate, start, end, pace, 0);
//call landing fuel
mode = &land;
land_result = mode
-> calcFuel();
total += land_result;
break;
case '4':
cout << "Enter distance for straight flight (meters): ";
cin >> distance;
cout << "Enter flight pace (meter/sec): ";
cin >> pace;
cout << "Fuel rate (kg/sec): ";
cin >> fuel_rate;

straight = Straight(0, fuel_rate, 0, 0, pace, distance);
//call straight fuel
mode = &straight;

str_result = mode -> calcFuel();
total += str_result;
break;
case '5':
cout <<"Total fuel requirement: "<< total << " kg"<< endl;
total = 0;
break;
case 'x':
return 0;
default:
continue;
}
}
return 0;
}

Я немного запутался в применении абстрактного дизайна фабрики. До сих пор я создал эти классы:

FlightModeInterface.h

class FlightModeInterface{

protected:
float time, fuel_rate, start, end, pace, distance;
float total;

public:
enum FLIGHT_MODES{
HOLDING,
RAISING,
LANDING,
STRAIGHT
};

FlightModeInterface(float, float, float,
float, float, float);

virtual ~FlightModeInterface(){ }

virtual float calcFuel() = 0;

static FlightModeInterface* createFactory(FLIGHT_MODES);
};

Holding.h

class Holding: public FlightModeInterface{
public:

Holding(float _time=0, float _fuel_rate=0, float _start=0,
float _end=0, float _pace=0, float _distance=0)
:FlightModeInterface(_time, _fuel_rate, _start, _end, _pace, _distance){ };

virtual float calcFuel(){
total = (time * fuel_rate * 60);
return total;
}
};

Landing.h

class Landing: public FlightModeInterface{

public:

Landing(float _time=0, float _fuel_rate=0, float _start=0,
float _end=0, float _pace=0, float _distance=0)
:FlightModeInterface(_time, _fuel_rate, _start, _end, _pace, _distance){ };

virtual float calcFuel (){
if(start > end && pace != 0 ){
float landing_time = (start - end)/pace;
total =  landing_time * fuel_rate;
return total;
}else{
return 0;
}
}
};

Raising.h

class Raising: public FlightModeInterface{
public:

Raising(float _time=0, float _fuel_rate=0, float _start=0,
float _end=0, float _pace=0, float _distance=0)
:FlightModeInterface(_time, _fuel_rate, _start, _end, _pace, _distance){ };

virtual float calcFuel (){

if(start < end && pace != 0 ){
float rising_time = (end - start)/pace;
total = rising_time * fuel_rate;
return total;
}else{
return 0;
}
}
};

Straight.h

class Straight: public FlightModeInterface{
public:

Straight(float _time=0, float _fuel_rate=0, float _start=0,
float _end=0, float _pace=0, float _distance=0)
:FlightModeInterface(_time, _fuel_rate, _start, _end, _pace, _distance){ };

virtual float calcFuel (){
if(distance != 0 || pace != 0 ){
float straight_time = distance/pace;
total = straight_time * fuel_rate;
return total;
}else{
return 0;
}
}
};

FlightModeFactory.cpp

class FlightModeFactory{
public:
static FlightModeInterface* createFactory(FlightModeInterface::FLIGHT_MODES mode){

if(mode == FlightModeInterface::FLIGHT_MODES::HOLDING){
//HOW TO FILL???
}
else if(mode == FlightModeInterface::FLIGHT_MODES::LANDING){

}
else if(mode == FlightModeInterface::FLIGHT_MODES::RAISING){

}else if(mode == FlightModeInterface::FLIGHT_MODES::STRAIGHT){

}

}
};

Как видите, я запутался с тем, как заполнять операторы if-else в FlightModeFactory.cpp. Любые идеи о том, как перейти к Factory Design Pattern с этого момента? Правильно ли заполнять методы calcFuel в Holding.h, Landing.h и т. Д.?

0

Решение

Использование

    if(mode == FlightModeInterface::FLIGHT_MODES::HOLDING){
//HOW TO FILL???
}
else if(mode == FlightModeInterface::FLIGHT_MODES::LANDING){

}
else if(mode == FlightModeInterface::FLIGHT_MODES::RAISING){

}
else if(mode == FlightModeInterface::FLIGHT_MODES::STRAIGHT){

}

плохая реализация. Лучшая реализация будет:

  1. Создать функцию для регистрации функций построителя.
  2. Регистрация функций построителя в разных режимах.
  3. Вызвать функцию строителя, учитывая mode,

FlightModeFactory.h:

class FlightModeFactory
{
public:

typedef FlightModeInterface* (*Builder)();

static void registerBuilder(FlightModeInterface::FLIGHT_MODES mode,
Builder builder);

static FlightModeInterface* build(FlightModeInterface::FLIGHT_MODES mode);
};

FlightModeFactory.cpp:

typedef std::map<FlightModeInterface::FLIGHT_MODES, FlightModeFactory::Builder> BuilderMap;

static BuilderMap& getBuilderMap()
{
static BuilderMap builderMap;
return builderMap;
}

void FlightModeFactory::registerBuilder(FlightModeInterface::FLIGHT_MODES mode,
Builder builder)
{
getBuilderMap()[mode] = builder;
}FlightModeInterface* FlightModeFactory::build(FlightModeInterface::FLIGHT_MODES mode)
{
Builder builder = getBuilderMap()[mode];
if ( builder )
{
return builder();
}
else
{
// assert()??
return nullptr;
}
}

Теперь зарегистрируйте функции компоновщика.

Holding.cc:

// Function to build a Holding.
static FlightModeInterface* buildHolding()
{
return new Holding;
}

// Register the builder function.
static int registerBuilder()
{
FlightModeInterface::registerBuilder(FlightModeInterface::FLIGHT_MODES::HOLDING,
buildHolder);
return 0;
}

static int dummy = registerBuilder();

Зарегистрируйте аналогичные функции для других подтипов FlightModeInterface.

1

Другие решения

--Iface
#pragma once
#include <iostream>
using namespace std;

class ISmart
{
public:
virtual string name() = 0;
};

class IDumm
{
public:
virtual string name() = 0;
};

--------
Ifaceimpl

#pragma once
#include <iostream>
#include "iface.h"
using namespace std;

class Asha : public IDumm
{
public:
string name()
{
return "Asha";
}
};

class Primo : public IDumm
{
public:
string name()
{
return "Primo";
}
};

class HTC4 : public IDumm
{
public:
string name()
{
return "Htc4";
}
};

class Lumia : public ISmart
{
public:
string name()
{
return "Lumia";
}
};

class Galaxy : public ISmart
{
public:
string name()
{
return "Galaxy";
}
};

class HTC8 : public ISmart
{
public:
string name()
{
return "HTC8";
}
};

AF

#pragma once
#include "iface.h"
enum phone { NOKIA = 0, SAMSUNG, HTC };

class AbstractFactory
{
public:
virtual ISmart* getSmart() = 0;
virtual IDumm* getDumm() = 0;
static AbstractFactory* GetFactory(enum phone);
};

-- -

AB Impl

#include "iface_impl.h"#include "AbstractFactory.h"
class Nokia : public AbstractFactory
{
public:

ISmart* getSmart()
{
return new Lumia();
}
IDumm* getDumm()
{
return new Asha();
}
};

class Samsung : public AbstractFactory
{
public:

ISmart* getSmart()
{
return new Galaxy();
}
IDumm* getDumm()
{
return new Primo();
}
};

class Htc : public AbstractFactory
{
public:

ISmart* getSmart()
{
return new HTC8();
}
IDumm* getDumm()
{
return new HTC4();
}
};

AbstractFactory* AbstractFactory::GetFactory(phone oem)
{
if (NOKIA == oem)
{
return new Nokia;
}
else if (SAMSUNG == oem)
{
return new Samsung;
}
else if (HTC == oem)
{
return new Htc;
}
return 0;
}

int main()
{
AbstractFactory* pFactory = AbstractFactory::GetFactory(NOKIA);
cout << "Factory is " << pFactory->getSmart()->name() << endl;
return 0;
}Compare your program
0