Just like you use constructor arguments which are very transparent in the terms of what is needed for the object to be created, one constructor may accept the
byte data type contaning serialized data for the object to be created.
As Telastyn has already pointed out, there's a problem with deserialization. It is very prone to errors because the
byte data types gives no hints about the data structure which may easily be corrupted by pretty much anything. Naturally, throwing an exception from a constructor is nothing to be afraid of and some people, myself included, encourage to do so when the input data is not in a valid format. Because of that, the
static factory method is really not needed as it pretty much just wraps the constructor anyway.
In my opinion the
static method brings nothing to the table and just like you can throw an exception with error info from the constructor you are very likely to do the same from the
static method anyway. You could introduce a
static getConstructionErrors method returning a list of error strings, but static state is shared and thus you may have issues related to race conditions.
But depending on your needs, you may not want a
static method or a constructor either. If you ever want to introduce another way of serialization/deserialization you should create a custom
FooSerialization interface (here the
interface is the language keyword and may me refered to as a
protocol or a
pure abstract class in other languages) and have different classes implement it to provide different serialization and deserialization strategies. Serialization and deserialization is usually not considered to be a direct responsibility of an object you are modeling and thus may be extracted to a custom service (see the Single Responsibility Principle). On the other hand, if you will never need more than one way to serialize the object, a direct
serialize method and construction from the serialized
byte array is probably the way to go.