これが私の問題であり、C ++でファクトリメソッドを使用することを検討していますが、あなたの意見は何ですか?
基本クラスと多くのサブクラスがあります。
TCP経由でネットワーク上のオブジェクトを転送する必要があります。
最初の側でオブジェクトを作成し、このオブジェクトを使用してバイト配列のTCPメッセージを作成し、それを反対側に送信します。
反対側では、TCPメッセージを分解し、オブジェクトを作成して、このオブジェクトをポリモーフィックキューに追加します。
これが私の問題であり、C ++でファクトリメソッドを使用することを検討していますが、あなたの意見は何ですか?
基本クラスと多くのサブクラスがあります。
TCP経由でネットワーク上のオブジェクトを転送する必要があります。
最初の側でオブジェクトを作成し、このオブジェクトを使用してバイト配列のTCPメッセージを作成し、それを反対側に送信します。
反対側では、TCPメッセージを分解し、オブジェクトを作成して、このオブジェクトをポリモーフィックキューに追加します。
簡単な答え: はい。
長い答え: ファクトリ メソッド パターンが必要です。
ネットワーク メッセージには、逆シリアル化するオブジェクトの型とサイズをメッセージ ヘッダーに含める必要があります。受信側では、ファクトリ メソッドが残りのメッセージ本文を消費して逆シリアル化し、オブジェクトを構築できます。
これを簡単にするための良い戦略は、すべてのクラスに、シリアル化してネットワーク経由でプライベート構造体に送信するデータを格納させることです。他のシリアル化されていないクラス データは、この構造体の外にあります。そうすれば、最小限の作業でネットワーク上の構造体全体をダンプできます。明らかに、クロス プラットフォーム (ビッグ エンディアンからリトル エンディアン、リトル エンディアンからビッグ エンディアン) に移行する場合は、バイト オーダーを考慮する必要があります。
このようなもの(頭のてっぺんから書いているだけなので、これは完璧にはほど遠いと確信しています):
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;
}
ソケットから読み取ったバッファをBike の _data 構造体として使用することで、メモリの断片化を回避することもできます。
いつものように、使用しているパターンを読むことは良い考えです。Factory Method Patternに関するウィキペディアの記事は次のとおりです。
Boost Serializationライブラリも調べる必要があります。エンディアンとワード サイズが異なるシステム間でデータをシリアル化するのに役立ちます。上記で詳しく説明した方法は非常に単純で、そのようなものは扱いません。
私が正しく理解している場合、現在の実装はエラーが発生しやすく、両側にプロセッサアーキテクチャのような多くのルーズエンドがあるため、IMHO、CORBA があなたのケースにより適しています。または、少なくともデータを転送するために何らかの表記法を使用できます。転送後、オブジェクトを作成および初期化するためのプロトタイプおよびビジター パターンを提案できます。それが役に立てば幸い。
「パラメータ化されたファクトリ メソッド」は非常に強力な逆シリアル化方法です。オブジェクトを取得し、そのデータに基づいて逆シリアル化を実行させます。
正確な要件に応じて、パターン指向ソフトウェア アーキテクチャの本にある Object-Request-Broker パターンを使用することをお勧めします。