Question: I've got a system that responds to messages. It represents messages by objects, but I've got at least 500 different kinds of messages. I don't want to make 500 classes. What do I do?
Answer: When you want classes to be reusable, but they are instead proliferating, they are usually too big. Decompose them.
A message has a set of fields. Each field holds a value (numeric, alphabetic) and has an offset in the original message. So, there will be a Message class and a Field class. In a statically typed language, you might have an IntegerField? and a StringField? class. The Fields are the objects that do the reading and writing to the data streams. The Message also has a read() and write() method, but it just iterates over its fields and has them do the work.
Each message has a type, which is also an object. You can use either the TypeObject pattern to have Message Types that describe messages, or you can use the Prototype pattern so that a message describes itself, and a message type is probably just a number. If you use Type Object then you will create a message by asking a MessageType? to read the input stream, while if you use Prototype then you'll have a prototypical message read it and create a clone of itself.
In either case, when you get an input stream to convert into a message, you first have to figure out which type of message it is. This is usually done by reading a type field at the start of the stream, and using it as an index into an array to get the Type or Prototype.
Don't forget SubjectVerbObject?.
You can use the CompositePattern for messages that have sequences of fields, to define common groups of fields, or to define record types.