Which way use of Factory is better(correct)?
IPacket info = PacketFactory.CreatePacketObject(PacketType.Info, currentUser, DateTime.Now, " disconnected");
or should I throw out second method in PacketFactory and use this one?
IPacket info = PacketFactory.CreatePacketObject(PacketType.Info);
info.CreationTime = DateTime.Now;
info.Creator = currentUser;
info.Data = " disconnected";
or maybe some other?
PacketFactory code:
public static class PacketFactory
{
public static IPacket CreatePacketObject(PacketType type)
{
IPacket packetToCreate = null;
switch (type)
{
case PacketType.Info:
packetToCreate = new Info();
break;
case PacketType.Log:
packetToCreate = new Log();
break;
case PacketType.Message:
packetToCreate = new Message();
break;
}
return packetToCreate;
}
public static IPacket CreatePacketObject(PacketType type, Client creator, DateTime creationTime, string data)
{
IPacket packetToCreate = null;
switch (type)
{
case PacketType.Info:
packetToCreate = new Info(creator, creationTime, data);
break;
case PacketType.Log:
packetToCreate = new Log(creator, creationTime, data);
break;
case PacketType.Message:
packetToCreate = new Message(creator, creationTime, data);
break;
}
return packetToCreate;
}
}
Before applying a pattern you should have a clear idea of what you gain by doing so, and in this instance I don’t really see that introducing a static “Factory” is gaining you anything. Look at it from the point of view of the client of the
PacketFactory: has introducing it reduced the coupling between the client and the various concrete implementors ofIPacket? I would argue not since the client already has to know which kind ofIPacketit wants by specifying a enumeration value of eitherPacketType.Info,PacketType.MessageorPacketType.Log. How is that any different from the client knowing about theInfo,MessageandLogclasses? Since the “Factory” is a static class the client is just as coupled to the type ofIPacketbeing returned as it would be if it just called the constructor of the appropriateIPacketimplementor because you would have to change the client in order for it to work with a different type ofIPacketin either case.So, if you really must use a Factory of some kind, then I would suggest employing the Abstract Factory pattern so that clients of the Factory would only depend on the factory interface and would therefore be able to work with different kinds of
IPacketwithout having to change. For example:As far as whether the factory should allow one to construct an
IPacketwithout specifying the creator, data and creation time or not depends on the class’s invariants. If the class invariants can be satisfied when the fields are not specified then that’s fine, otherwise they should be required. A part of a class’s job should be to ensure that it cannot be constructed in an invalid state since users of the class will be depending upon that to be the case.In the case where one of the
IPacketimplementors needs extra parameters:The Abstract Factory pattern needs there to be a uniform interface for all implementers, so if it makes sense for all the factories to have a Create method with the extra parameters then you can add them to the interface. One form of this is to pass an object with various properties/methods that the
Createmethod can use to derive the extra parameter values it needs. A special case is Double Dispatch where the caller passes itself (in this case the Client) and is then called from inside the Create method.You need to remember that the goal is to abstract the type of
IPacketbeing created, so if whilst implementing this approach you start to get the feeling that theClientis starting to implicitly know the specific type being constructed then you may have to take a step back and consider if the factory is appropriate at all. Your only other option is to provide the extra information when you construct the factory (i.e. pass it to the constructor).Those represent some of the options, but in any case, I would strongly advise that you do not use a static or singleton “Factory” class because it will strongly-couple your client class to the factory and most likely the
IPacketsubclass.