Pergunta

here is my problem and I'm considering to use factory method in C++, what are your opinions ?

There are a Base Class and a lot of Subclasses.

I need to transfer objects on network via TCP.

I will create objects in first side, and using this object I will create a byte array TCP message, and send it to other side.

On the other side I will decompose TCP message, I will create object and I will add this object to a polymorphic queue.

Foi útil?

Solução

Short answer: Yes.

Long Answer: The factory method pattern is what you want.

Your network messages need to include the type and size of the object to deserialize in the message header and then on the recipient side your factory method can consume and deserialize the rest of the message body to construct the objects.

A good strategy to make this simple is to have all your classes store the data that they will be serialising and sending over the wire in a private struct. Other non-serialized class data would be outside this struct. That way you can just dump the whole struct on the network with minimal work. Obviously you may have to take into account byte order considerations if you're going cross platform (ie, big to little or little to big endian).

Something like this (I'm sure this is far from perfect as I'm just writing it off the top of my head):

enum VehicleType  
{
  VehicleType_Car,
  VehicleType_Bike
};

class Vehicle 
{
   virtual size_t GetDataSize() = 0;
   virtual void* GetData() = 0;
};

class Bike : Vehicle
{
private:
    VehicleType _type;
    size_t _dataSize;
    struct BikeData
    {
       char[100] name;
       // etc 
    } _data;
public:
    Bike(void* data)
      : Bike(static_cast<BikeData*>(data)->name) 
    {
    }

    Bike(char[]& name) 
      : _type(VehicleType_Bike), _dataSize(sizeof(BikeData))
    {
       memset(&_data.name, 0, 99);
       strncpy(&_data.name, name, 99);
    }

    virtual size_t GetDataSize() { return _dataSize; }
    virtual void* GetData() { return &_data; }
};

class Car : Vehicle
{
    // etc
};


void SendVehicle(int socket, const Vehicle& vehicle)
{
    write(socket, vehicle.GetData(), vehicle.GetDataSize());  
}

Vehicle* ReceiveVehicle(int socket)
{
    VehicleType type;
    size_t dataSize;

    read(socket, &type, sizeof(VehicleType));
    read(socket, &dataSize, sizeof(size_t));

    BYTE* data = new BYTE[dataSize];
    read(socket, &data, dataSize);

    Vehicle v* = CreateVehicle(type, dataSize, data);
    delete[] data;

    return v;
}

// The factory method.
Vehicle* CreateVehicle(VehicleType type, size_t dataSize, void* data)
{
    switch(type)
    {
        case VehicleType_Car: return new Car(data);
        case VehicleType_Bike: return new Bike(data);
    }

    return 0;
}

You could even avoid some memory fragmentation by using the buffer you read off the socket as the Bike's _data structure.

As always, reading up on the pattern you're using is a good idea. Here is the Wikipedia article on the Factory Method Pattern.

You should also look into the Boost Serialization library. It it will help you serialize data across systems with different endianness and word sizes. The method I have detailed above is very simple and doesn't deal with stuff like that.

Outras dicas

"Parametrized factory method" is a very powerful way of deserializing: get your object and let it do the deserializing based on its data.

If I understand correctly, your current implementation is error prone, there are many loose ends like processor architecture on both sides, therefore, IMHO, CORBA suits better for your case. Or at least you may use some notation to transfer data. After the transfer, I can suggest Prototype and Visitor patterns to create and initialize your objects. Hope it helps.

Depending on your exact requirements I would suggest using the Object-Request-Broker pattern, which can be found in the Pattern Oriented Software Architecture books.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top