关键字:日志 微软企业库 Log4net 工厂模式
上一篇我们介绍了一个简单的日志组件,SimpleLog,实现了一个ISimpleLog接口与三个具体的日志类。现在我们需要系统中的日志是可以被替换的,即可以使用我们自己开发的SimpleLog日志组件,也可以使用微软企业库的日志组件或者是Log4net组件等等。闲话少说,我们直接进入代码。
首先,我们定义一个日志接口。
public interface ILog {
void AddLog(string Msg);
void AddLog(string Msg, DateTime time);
}
因为我们要使用不同类型的日志组件,所以我们需要对这些日志组件进行简单的包装,以便不同的日志组件能符合我们定义的接口。
先来包装SimpleLogWrapper:
public class SimpleLogWrapper {
public readonly string SimpleLogClassName = ConfigurationManager.AppSettings["SimpleLogClassName"];
public void AddLog(string text) {
ISimpleLog log = (ISimpleLog)Assembly.Load("IVSoft.Log.SimpleLog").CreateInstance(SimpleLogClassName);
log.AddLog(text);
}
public void AddLog(string Msg, DateTime time) {
ISimpleLog log = (ISimpleLog)Assembly.Load("IVSoft.Log.SimpleLog").CreateInstance(SimpleLogClassName);
log.AddLog(Msg, time);
}
}
再包装微软企业库的日志组件(微软企业库日志的使用方法可以看http://www.cnblogs.com/Terrylee/archive/2005/11/02/266999.html):
public class MSLogWrapper : ILog {
public void AddLog(string Msg) {
AddLog(Msg, DateTime.Now);
}
public void AddLog(string Msg, DateTime time) {
LogEntry log = new LogEntry();
log.Message = Msg;
log.TimeStamp = time;
log.Title = "";
Logger.Write(log);
}
}
再来包装Log4net的日志组件(Log4net日志组件的使用方法可以看http://blog.csdn.net/zhoufoxcn/archive/2008/03/26/2220533.aspx):
public class Log4netWrapper :ILog {
public void AddLog(string Msg) {
AddLog(Msg, DateTime.Now);
}
public void AddLog(string Msg, DateTime time) {
//创建日志记录组件实例
log4net.ILog log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
//记录错误日志
log.Info(Msg);
}
}
包装完成之后,我们就可以再客户端的代码进行调用了,但是我们现在想通过配置文件(App.config)来设置使用的日志,这样方便日志的更新,而且客户端的代码也是不用更改的,那么我们这个时候就请出“工厂模式”,看如下代码:
public class LogFactory {
public readonly string LogAssemblyName = ConfigurationManager.AppSettings["LogAssemblyName"];
public readonly string LogNameSpaceClassName = ConfigurationManager.AppSettings["LogNameSpaceClassName"];
public ILog GetLogInstance() {
return (ILog)Assembly.Load(LogAssemblyName).CreateInstance(LogNameSpaceClassName);
}
}
这里面用到了反射,通过反射来调用相应的DLL并创建配置中指定的日志类的实例。
这样我们的客户端的代码就可以这么写了:
LogFactory factory = new LogFactory();
ILog log = factory.GetLogInstance();
log.AddLog("测试日志消息");
我们在来看看App.config的配置文件中与日志工厂相关的配置节:
<appSettings>
<add key="LogAssemblyName" value="IVSoft.Log.MSLogWrapper" />
<add key="LogNameSpaceClassName" value="IVSoft.Log.MSLogWrapper" />
</appSettings>
其中:LogAssemblyName 是指日志组件所在的DLL文件名,我们这里都是 XXXLogWrapper;LogNameSpaceClassName是指日志组件的类名,包括名称空间。
这样,将来可以通过更改配置文件的相关节来使用不同的日志组件,而你的这段客户端代码是不需要做任何的更改的,这就将客户端代码与日志组件的代码做了解耦,而做到这一点的正式“工厂模式”。
下面我们来看看工厂模式的定义:
Factory Method模式是一种对象创建型模式,它把类的实例的创建延迟到子类中完成,父工厂类只定义创建对象的公共接口,而子工厂类则负责生成具体的类的实例。
虽然我们这里只有一个工厂类,没有子工厂类,但是其实我们是通过了反射完成了这个过程,正常的工厂类我们可能会写死每个日志类(ILog = new MSLogWarpper()),这样就失去了一些灵活性,我们的实现方法是一个变通的做法。
标准的Factory Method 模式图:
使用工厂模式的最大优点就是将客户代码与实际的类解耦,即使将来更改实际类,客户的代码也不会发生改变。
何时该使用工厂模式:如果你现在不确定将来要使用那些实际类或者实际类可能会有多个,可以使用工厂模式来返回是实际类的接口(抽象类)。
这也是我的第一篇有关于设计模式的文章,欢迎大家拍砖。