日志与工厂模式(二)

关键字:日志 微软企业库 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 模式图:

2009-06-12_164022

使用工厂模式的最大优点就是将客户代码与实际的类解耦,即使将来更改实际类,客户的代码也不会发生改变。

何时该使用工厂模式:如果你现在不确定将来要使用那些实际类或者实际类可能会有多个,可以使用工厂模式来返回是实际类的接口(抽象类)。

这也是我的第一篇有关于设计模式的文章,欢迎大家拍砖。

点击这里下载代码

posted @ 2009-06-12 17:17  老姜  阅读(2744)  评论(10编辑  收藏  举报