2015-09-26 2 views
0

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

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

#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; 
} 

Я немного запутался для применения Abstract Factory Design. До сих пор я создал эти классы:

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 и т. Д.?

+2

'// КАК ЗАПОЛНИТЬ' нечто вроде 'return new Holding (...);'. Но я на самом деле рекомендую ввести возвращаемый 'std :: unique_ptr 'вместо исходного указателя. –

+1

Вам нужно заменить '// HOW TO FILL ???' на 'return new Holding (...);', но вам также необходимо передать все переменные-конструкторы в ваш заводский метод. Однако это не похоже на дизайн «Абстрактной фабрики» для меня. Я подумал, что именно там вы создали конкретную фабрику для каждого типа объектов, которые хотите моделировать, скажем, если бы у вас были разные типы самолетов, у каждого из которых был набор поведенческих «компонентов». – Galik

+1

Также я бы рассмотрел возможность вывести все переменные из конструктора и передать их функции 'calcFuel();'. Тогда ваш класс интерфейса может быть действительно чистым интерфейсом класса *, и вам не нужно передавать все эти переменные на заводский метод. В принципе, завод предоставляет расчетный объект для каждого типа маневра. – Galik

ответ

1

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

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

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

Холдинг.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.

0
--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 
Смежные вопросы