I'm writing a service to parse machine log files as they are written to a central directory and push them to a web service. Each machine generates several log files at a time, with each file encapsulating a particular domain of operational information (e.g. user login sessions, errors, statistics, etc.).
The log files are written by different models of machines from different manufacturers. All the machines generate the same kinds of information, but the structure of the log files differs according to the manufacturer of the machine and the type of information the log file contains. Below is a sketch of a set of factories that will create Log classes for each type of log file and configure them with a Parser appropriate for that manufacturer (Strategy Pattern).
Over time new machines will be added to the logging pool and it should be straightforward to add support for these. The proposed design is arranged around the manufacturer and it makes it simple to add support for new manufacturers. However, I am concerned about a scenario in which a new model from an existing manufacturer does not adhere to that manufacturer's existing log format.
Is there a better design?
public interface ILogFactory
{
ISessionLog CreateSessionLog();
ITipLog CreateTipLog();
IStatisticsLog CreateStatisticsLog();
}
public class SmithsLogFactory : ILogFactory
{
public ISessionLog CreateSessionLog()
{
return new SessionLog() { Parser = new SmithsSessionStrategy(); }
}
public ITipLog CreateTipLog()
{
return new TipLog() { Parser = new SmithsTipStrategy(); }
}
public IStatisticsLog CreateStatisticsLog()
{
return new StatisticsLog() { Parser = new SmithsStatsStrategy(); }
}
}
public class L3LogFactory : ILogFactory
{
public ISessionLog CreateSessionLog()
{
return new SessionLog() { Parser = new L3SessionStrategy(); }
}
public ITipLog CreateTipLog()
{
return new TipLog() { Parser = new L3TipStrategy(); }
}
public IStatisticsLog CreateStatisticsLog()
{
return new StatisticsLog() { Parser = new L3StatsStrategy(); }
}
}
public class VividFactory : ILogFactory
{
public ISessionLog CreateSessionLog()
{
return new SessionLog() { Parser = new VividSessionStrategy(); }
}
public ITipLog CreateTipLog()
{
return new TipLog() { Parser = new VividTipStrategy(); }
}
public IStatisticsLog CreateStatisticsLog()
{
return new StatisticsLog() { Parser = new VividStatsStrategy(); }
}
}
-
\$\begingroup\$ What is your issue with worst-case scenario you proposed? If you encounter new log format - you simply create a new strategy. Why does it matter if format changes due to new manufacturer or due to new model of existing manufacturer? \$\endgroup\$Nikita B– Nikita B2014年01月22日 06:02:06 +00:00Commented Jan 22, 2014 at 6:02
1 Answer 1
Few thoughts about your code:
your case resembles more
Abstract Factory
pattern more thanStrategy
pattern.ILogFactory
is yourAbstract Factory
whileSmithsLogFactory
,VividFactory
etc are yoursConcrete Factories
.ISessionLog
,ITipLog
andIStatisticsLog
areAbstract Products
and, for example,TipLog
withL3TipStrategy
inside is yourProduct
.Because I see this case as
Abstract Factory
, I would add derived versions ofISessionLog
,ITipLog
andIStatisticsLog
for each manufacturer. Constructor of each of those classes should take care of details - like creating proper version ofParser
subclass.When using
Abstract Factory
I always like to provide * construction parameters* to the methods, which can be used to control concrete products creation - and here is the place where I would handle issue with different versions of the logs from the same manufacturer.
Draft summarizing my thoughts:
public class LogFactoryParameters
{
// ... for example, Version
}
public class L3LogFactory : ILogFactory
{
public ISessionLog CreateSessionLog(LogFactoryParameters parameters)
{
return new L3SessionLog(parameters);
}
public ITipLog CreateTipLog(LogFactoryParameters parameters)
{
return new L3TipLog(parameters);
}
public IStatisticsLog CreateStatisticsLog(LogFactoryParameters parameters)
{
return new L3StatisticsLog(parameters);
}
}
-
\$\begingroup\$ I would say that an Abstract Factory pattern also is a Strategy pattern (
AbstractFactoryPattern
extendsStrategyPattern
) \$\endgroup\$Simon Forsberg– Simon Forsberg2014年01月22日 12:03:48 +00:00Commented Jan 22, 2014 at 12:03