工厂方法模式实现多功能日志记录

有时,我们在开发的时候,会遇到一些关于日志记录的功能。并且,它们可能是独立于系统业务逻辑的,那么我们就可以将日志做成组件的形式,以方便复用。

以下采用工厂方法模式,来实现日志组件的设计,并保证对功能的扩展不会改变已有的实现。

我们实现三种日志记录类型:错误日志记录、按钮点击日志记录、操作日志记录。

首先,我们创建一个“抽象工厂”【其实是各实例工厂都必须实现的Log接口】,既然是日志记录,那么就需要有日志的实体了。也就是LogEntity,它是一个“抽象实体”,因为不同类型的日志,需要不同的日志实体,所以这里采用LogEntity作为抽象实体,来派生出各具体类型的日志实体。

实现如下:

public interface ILogFactory
    {
        void Log(LogEntity logEntity);
    }

/// <summary>
    /// 日志实体(抽象基类)
    /// </summary>
    public abstract class LogEntity
    {
        public override string ToString()
        {
            return "LogEntity(abstract class)";
        }
    }

以下是各个实例工厂、和日志实体,实现各自的日志记录逻辑:

/// <summary>
    /// 记录错误日志实体类
    /// </summary>
    public class ErrorEntity:LogEntity
    {
        /// <summary>
        /// 编号
        /// </summary>
        public string ID { get; set; }

        /// <summary>
        /// 用户编号
        /// </summary>
        public string UserID { get; set; }

        /// <summary>
        /// 页面URL
        /// </summary>
        public string PageUrl { get; set; }

        /// <summary>
        /// 错误信息
        /// </summary>
        public string Msg { get; set; }

        /// <summary>
        /// 发生时间
        /// </summary>
        public DateTime OperateTime { get; set; }

    }

public class ErrorFactory : ILogFactory
    {

        private const string FullClassName = "LogComponent.ErrorFactory";

        public void Log(LogEntity logEntity)
        {
            #region check args
            if (logEntity == null)
            {
                throw new ArgumentNullException(string.Format("The Method in {0} occur ArgumentNullException", FullClassName));
            }

            ErrorEntity innerEntity = logEntity as ErrorEntity;

            if (innerEntity == null)
            {
                throw new NullReferenceException(string.Format("The Method in {0} occur NullReferenceException.Because of converting type.", FullClassName));
            }

            if (string.IsNullOrEmpty(innerEntity.Msg))
            {
                throw new Exception(string.Format("The Method in {0} occur logic Exception. Because of the error message is not nullable", FullClassName));
            }
            #endregion

            //记录日志
            string sql = @"INSERT INTO SYSTEMERRORINFO(SE_USERID,SE_PAGEURL,SE_MESSAGE,SE_OPERATETIME) values (:SE_USERID,:SE_PAGEURL,:SE_MESSAGE,:SE_OPERATETIME)";
            OracleParameter[] parameters = new OracleParameter[]
            {
                new OracleParameter(":SE_USERID",innerEntity.UserID==null?"":innerEntity.UserID),
                new OracleParameter(":SE_PAGEURL",innerEntity.PageUrl==null?"":innerEntity.PageUrl),
                new OracleParameter(":SE_MESSAGE",innerEntity.Msg==null?"":innerEntity.Msg),
                new OracleParameter(":SE_OPERATETIME",innerEntity.OperateTime==DateTime.MinValue?DateTime.Now:innerEntity.OperateTime)
             };

            OracleHelper.ExecuteNonQuery(OracleHelper.ConnectionStringLocalTransaction, CommandType.Text, sql, parameters);

        }

    }

/// <summary>
    /// 点击按钮统计--其中ButtonName为必填字段
    /// </summary>
    public class ClickCountEntity:LogEntity
    {
        /// <summary>
        /// 记录编号
        /// </summary>
        public string ID { get; set; }

        /// <summary>
        /// 用户ID
        /// </summary>
        public string UserID { get; set; }

        /// <summary>
        /// 页面Url
        /// </summary>
        public string PageUrl { get; set; }

        /// <summary>
        /// 操作时间
        /// </summary>
        public DateTime OperateTime { get; set; }

        /// <summary>
        /// 路径名称
        /// </summary>
        public string PathName { get; set; }

        /// <summary>
        /// 按钮名称
        /// </summary>
        public string ButtonName { get; set; }
    }

public class ClickCountFactory:ILogFactory
    {

        private const string FullClassName = "LogComponent.ClickCountFactory";
        private ErrorEntity errorEntity = null;

        public void Log(LogEntity logEntity)
        {
            //check args
            if (logEntity==null)
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = string.Format("The method in {0} occur ArgumentNullException.Because of the arg: logEntity is not nullable.", FullClassName);
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw new ArgumentNullException(string.Format("The method in {0} occur ArgumentNullException.Because of the arg: logEntity is not nullable.", FullClassName));
            }

            ClickCountEntity innerEntity = logEntity as ClickCountEntity;
            if (innerEntity==null)
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = string.Format("The method in {0} occur NullReferenceException.Becaues of converting type", FullClassName);
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw new NullReferenceException(string.Format("The method in {0} occur NullReferenceException..Becaues of converting type", FullClassName));
            }

            if (String.IsNullOrEmpty(innerEntity.ButtonName))
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = string.Format("The method in {0} occur Exception.Because of the field ButtonName is not nullable.", FullClassName);
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw new Exception(string.Format("The method in {0} occur Exception.Because of the field ButtonName is not nullable.", FullClassName));
            }

            string sql = @"INSERT INTO buttonclickstatistic
                           (bs_userid, bs_pageurl, bs_buttonid, bs_operatetime, bs_pathname, bs_buttonname)
                           VALUES
                           (:v_bs_userid, :v_bs_pageurl, :v_bs_buttonid, :v_bs_operatetime, :v_bs_pathname, :v_bs_buttonname)";

            OracleParameter[] parameters = new OracleParameter[]{
               new OracleParameter(":v_bs_userid",innerEntity.UserID==null?"":innerEntity.UserID),
               new OracleParameter(":v_bs_pageurl",innerEntity.PageUrl==null?"":innerEntity.PageUrl),
               new OracleParameter(":v_bs_buttonid",innerEntity.ID==null?"":innerEntity.ID),
               new OracleParameter(":v_bs_operatetime",innerEntity.OperateTime),
               new OracleParameter(":v_bs_pathname",innerEntity.PathName==null?"":innerEntity.PathName),
               new OracleParameter(":v_bs_buttonname",innerEntity.ButtonName)
            };

            try
            {
                OracleHelper.ExecuteNonQuery(OracleHelper.ConnectionStringLocalTransaction, CommandType.Text, sql, parameters);
            }
            catch (Exception ex)
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = ex.Message + ex.StackTrace;
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw;
            }
            
        }

    }

/// <summary>
    /// 操作日志实体类--其中Msg为必填字段
    /// </summary>
    public class OperatingEntity:LogEntity
    {
        /// <summary>
        /// 记录编号
        /// </summary>
        public string ID { get; set; }

        /// <summary>
        /// 用户Id
        /// </summary>
        public string UserID { get; set; }

        /// <summary>
        /// 操作日志
        /// </summary>
        public string Msg { get; set; }

        /// <summary>
        /// 操作时间
        /// </summary>
        public DateTime OperatingTime { get; set; }

        /// <summary>
        /// 登陆时间
        /// </summary>
        public DateTime LoginTime { get; set; }

        /// <summary>
        /// 下线时间
        /// </summary>
        public DateTime LogoutTime { get; set; }


    }

public class OperatingFactory:ILogFactory
    {
        private const string FullClassName = "LogComponent.OperatingFactory";
        private ErrorEntity errorEntity = null;

        public void Log(LogEntity logEntity)
        {
            //check args
            if (logEntity==null)
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = string.Format("The method in {0} occur ArgumentNullException.Because of the arg: {1} is not nullable", FullClassName, "logEntity");
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw new ArgumentNullException(string.Format("The method in {0} occur ArgumentNullException.Because of the arg: {1} is not nullable", FullClassName, "logEntity"));

            }

            OperatingEntity innerEntity = logEntity as OperatingEntity;
            if (innerEntity==null)
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = string.Format("The method in {0} occur NullReferenceException.Because of Converting type.", FullClassName);
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw new NullReferenceException(string.Format("The method in {0} occur NullReferenceException.Because of Converting type.", FullClassName));
            }

            if (string.IsNullOrEmpty(innerEntity.Msg))
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = string.Format("The method in {0} occur Exception.Because of the field:Msg is not nullable.",FullClassName);
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw new Exception(string.Format("The method in {0} occur Exception.Because of the field:Msg is not nullable.", FullClassName));
            }

            //记录日志
            string sql = @"INSERT INTO operatinglog(ol_uf_id,ol_msg,ol_op_time,ol_li_time,ol_lo_time) 
                                             VALUES(:ol_uf_id,:ol_msg,:ol_op_time,:ol_li_time,:ol_lo_time)";

            OracleParameter[] paras = new OracleParameter[]
            {
                new OracleParameter(":ol_uf_id",innerEntity.UserID==null?"":innerEntity.UserID),
                new OracleParameter(":ol_msg",innerEntity.Msg),
                new OracleParameter(":ol_op_time",innerEntity.OperatingTime),
                new OracleParameter(":ol_li_time",innerEntity.LoginTime),
                new OracleParameter(":ol_lo_time",innerEntity.LogoutTime),
            };

            try
            {
                OracleHelper.ExecuteNonQuery(OracleHelper.ConnectionStringLocalTransaction, CommandType.Text, sql, paras);
            }
            catch (Exception ex)
            {
                errorEntity = new ErrorEntity();
                errorEntity.Msg = ex.Message + ex.StackTrace;
                ILogFactory logFactory = new ErrorFactory();
                logFactory.Log(errorEntity);

                throw;
            }
            
        }
    }

在客户端调用的时候,你需要先new 一个你需要的具体的日志实体,然后设置它的属性,比如:

OperatingEntity entity=new OperatingEntity();

//set Property

entity.OperatingTime=DateTime.Now;

.....

然后提供你的实例工厂:

ILogFactory factory=new OperatingFactory();

factory.Log(entity);


扩展的时候,你需要构建你新的日志实体类和新的实例工厂,来实现你的记录逻辑。

原有的实现都无需改动。




原文发布时间为:2011-07-24


本文作者:vinoYang


本文来自云栖社区合作伙伴CSDN博客,了解相关信息可以关注CSDN博客。

上一篇:MySQL测试工具 sysbench简单安装使用测试~~


下一篇:MongoDB 日志切换(Rotate Log Files)实战