У меня есть программа, где пользователь вводит операции самолета. Пользователь может выбрать столько операций (удержание, прямой, посадка и т. Д.), Сколько ему нужно. Пользователь может рассчитать необходимый расход топлива с помощью операции 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 и т. Д.?
Использование
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){
}
плохая реализация. Лучшая реализация будет:
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.
--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