灵活的设计,以取代开关声明

时间:2011-06-15 07:54:52

标签: c++ networking

我正在开发网络程序并使用C ++设计Linux服务器。设计基本结构非常简单。我有一个数据包定义,其头部具有固定的大小。

typedef enum{
     PACKET_LOGIN_REQ = 1,
     PACKET_LOGIN_RES,
     PACKET_STORE_REQ,
     PACKET_STORE_RES
}PACKET_TYPES;

typedef struct {
     PACKET_TYPES type;
     short bodySize,
     long long deviceId
}HEADER;

.
.

/*more definitions here*/

typedef struct{
     HEADER head;
     union BODY{
          LOGIN_REQ loginReq;
          LOGIN_RES loginRes;
          .
          .
          more types
     }
}

每当我添加更多数据包类型时,我都必须修改switch语句以添加更多案例来处理新添加的数据包。

我正在使用union类型,所以我不必更改整个数据包结构。相反,我可以将新添加的数据包类型添加到联合结构中。

但是,当我尝试使用switch语句解析原始数据以放入数据包时,我每次都必须添加每个switch语句。

我认为这不是一个好的设计模式,我想知道如何以更灵活的方式设计结构。

有没有更好的方法来处理这个问题(更好的设计模式)?相关的教程或参考怎么样?

4 个答案:

答案 0 :(得分:7)

您应该使用类而不是switch使用多态调用。

类似的东西(伪编码):

class Packet{
public:
   Packet();
   virtual ~Packet();
   virtual HandleMe()=0;
protected:
   // fields 
}

PacketTypeOne: public Packet{
public:
  virtual HandleMe(); // implementation for type 1
}

PacketType2: public Packet{
public:
  virtual HandleMe(); // implementation for type 2
}

PacketTypeX: public Packet{
public:
  virtual HandleMe(); // implementation for type X
}

以及获取数据包的地方:

...
Packet* newPacket = PacketFactory::CreateNewPacket(packetTypeX); // factory will create
              // the right instance.
...
// now handle it:
newPacket->HandleMe();
...

完成。

答案 1 :(得分:3)

由于你的代码是C风格而不是C ++风格代码,我会给你C答案。

使用函数指针。类似的东西:

typedef int (*ParseFunc)(const char *, len, struct MyStruct);

typedef struct PacketParser_
{
    PACKETType type;
    ParseFunc parseFunc;
} PacketParser;

const PacketParser[] parser = 
{
   { PACKET_LOGIN_REQ, LoginReqParser }
   { PACKET_LOGIN_RES, LoginResParser }
   .
   .
   .
}

然后遍历所有数据包类型并调用相应的函数。每当您获得新的数据包类型时,只需在PacketParser函数中添加另一行。

如果您使用的是C ++,最好使用多态。

答案 2 :(得分:1)

在大多数情况下,您应该避免使用union。这是其中一种情况: - )

如上所述,答案是使用多态性。将switch语句转换为多态的规范方法是使用Visitor design pattern

虽然正常的多态性,使用virtual方法可以帮助你,但是存在问题。 virtual方法可以根据单个对象(Packet)为您分配正确的方法。但是,您还要依赖采取的行动。例如,如果您有许多switch个语句而不是一个,那么Visitor模式将更可取。

答案 3 :(得分:0)

你可能想......

基本上,你会找到一个好的超类,并为每个类型代码创建一个不同的子类。

您还想购买 “重构:改进现有代码设计”的副本。 ,Fowler,Martin(1999)/ Addison Wesley。