在C ++中应用抽象工厂设计模式

时间:2015-09-26 18:44:12

标签: c++ design-patterns abstract-factory

我有一个用户输入飞机操作的程序。用户可以根据需要选择任意数量的操作(保持,直线,着陆等)。用户可以通过操作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){

        }

    }
};

正如您所看到的,我对如何填充FlightModeFactory.cpp中的if-else语句感到困惑。关于如何从这一点继续工厂设计模式的任何想法?在Holding.h,Landing.h等中填写calcFuel方法是否正确?

2 个答案:

答案 0 :(得分: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
  4. 的情况下调用构建器函数

    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 :(得分:0)

[supervisord]
nodaemon=true
logfile=/var/log/supervisor/supervisord.log
pidfile = /tmp/supervisord.pid

[program:rserver]
user=root
command=/usr/lib/rstudio-server/bin/rserver
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
startsecs=0
autorestart=false
exitcodes=0

[program:shinyserver]
user=root
startsecs = 0
command=/bin/bash -c "exec shiny-server >> /var/log/shiny-server.log 2>&1"
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
autorestart=false
redirect_stderr=true