在C ++中应用抽象工厂设计模式 [英] Applying Abstract Factory Design Pattern in C++

查看:173
本文介绍了在C ++中应用抽象工厂设计模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序,用户输入飞机的操作。用户可以选择与他/她想要一样多的操作(保持,直,着陆等)。用户可以通过操作5计算必要的燃料摄入量。

I have a program where user enters the operations of a plane. User can select as many operations (holding, straight, landing etc.) as s/he wants. User can calculate the necessary fuel intake with operation 5.

我决定对我的代码应用抽象工厂设计模式。这里是应用没有模式的代码的当前版本:

I have decided to apply Abstract Factory Design Pattern to my code. Here is the current version of the code without pattern is applied:

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



我对抽象工厂设计的应用有点困惑。到目前为止,我已经创建了这些类:

I'm a bit confused for the application of the Abstract Factory Design. So far I have created these classes:

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方法是正确的吗?

As you can see, I got confused with how to fill the if-else statements in FlightModeFactory.cpp. Any ideas on how to continue to Factory Design Pattern from this point? Is it correct to fill the calcFuel methods in Holding.h, Landing.h etc.?

推荐答案

使用

    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){

    }

是一个很差的实现。更好的实现方法是:

is a poor implementation. A better implementation would be:


  1. 创建一个函数来注册构建函数。

  2. 注册构建函数

$ b

  • 调用模式
    $ b

    FlightModeFactory.h:

    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:

    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:

    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的其他子类型注册类似的函数。

    Register similar functions for other sub-types of FlightModeInterface.

    这篇关于在C ++中应用抽象工厂设计模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆