回到目录

之前的讲过两篇关于日志组件的文章,分别是《第一回  日志记录组件之自主的Vlog》和《第三回  日志记录组件之log4net》,而今天主要说一下我自己开发的另一种日志组件Logger.Core,它也属于面试AOP(横切关注点)的一部分,这个组件对于一些想学习设计模式的同学来说,无疑是一个大餐!Logger.Core项目里内含了策略模式模版方法模式工厂模式单例模式,可以说,最常用的模式都用到了,而它们在这个项目里都起到了什么作用,什么时候用到它们呢,这些答案相信在看完我的文章之后,您会有一个明确的答案的。

一 面向接口编程与多态

面向接口编程,是实现软件解耦的灵魂,也是实现多态的方法之一,日志项目有统一的接口规范

    /// <summary>
/// 日志功能接口规范
/// </summary>
public interface ILogger
{
/// <summary>
/// 记录代码运行时间
/// </summary>
/// <param name="message">消息</param>
/// <param name="action">所测试的代码块</param>
/// <param name="fileName">日志文件名</param>
void Logger_Timer(string message, Action action, string fileName); /// <summary>
/// 记录代码运行时间,日志文件名以codeTime开头的时间戳
/// </summary>
/// <param name="message">消息</param>
/// <param name="action">所测试的代码块</param>
void Logger_Timer(string message, Action action); /// <summary>
/// 记录代码运行异常
/// </summary>
/// <param name="message">消息</param>
/// <param name="action">要添加try...catch的代码块</param>
/// <param name="fileName">日志文件名</param>
void Logger_Exception(string message, Action action, string fileName); /// <summary>
/// 记录代码运行异常,日志文件名以Exception开头的时间戳
/// </summary>
/// <param name="message">消息</param>
/// <param name="action">要添加try...catch的代码块</param>
void Logger_Exception(string message, Action action); /// <summary>
/// 将message记录到日志文件
/// </summary>
/// <param name="message"></param>
void Logger_Info(string message); /// <summary>
/// 将message记录到名为fileName的日志文件
/// </summary>
/// <param name="message"></param>
/// <param name="fileName"></param>
void Logger_Info(string message, string fileName);
}

二 继承与面向对象

继承是面向对象的三大特性之一,有了它,面向对象才有了层次感,将公共的功能点从各个派生类抽出,提取到基类中

    /// <summary>
/// 日志核心基类
/// 模版方法模式,对InputLogger开放,对其它日志逻辑隐藏,InputLogger可以有多种实现
/// </summary>
internal abstract class LoggerBase : ILogger
{
private string _defaultLoggerName = DateTime.Now.ToString("yyyyMMddhh") + ".log"; /// <summary>
/// 日志文件地址
/// 优化级为mvc方案地址,网站方案地址,console程序地址
/// </summary>
protected string FileUrl
{
get
{
try
{ return System.Web.HttpContext.Current.Server.MapPath("/Logger/"
+ System.Web.HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString()
+ "/"
+ System.Web.HttpContext.Current.Request.RequestContext.RouteData.Values["action"].ToString()
+ "/"); //例如:c:\\project\\Logger\\Home\\Index\\
}
catch (NullReferenceException)
{
try
{
return System.Web.HttpRuntime.AppDomainAppPath + "LoggerDir\\"; //例如:c:\\project\\
}
catch (ArgumentNullException)
{ return Environment.CurrentDirectory + "\\LoggerDir\\"; //例如:c:\\project\\bin\\debug
} }
}
} protected abstract void InputLogger(string message, string fileName); #region ILogger 成员 public void Logger_Timer(string message, Action action, string fileName)
{
StringBuilder str = new StringBuilder();
Stopwatch sw = new Stopwatch();
sw.Restart();
str.Append(message);
action();
str.Append("代码段运行时间:" + sw.ElapsedMilliseconds + "毫秒");
InputLogger(str.ToString(), string.IsNullOrWhiteSpace(fileName)
? "CodeTime" + _defaultLoggerName
: fileName);
sw.Stop();
} public void Logger_Timer(string message, Action action)
{
Logger_Timer(message, action, null);
} public void Logger_Exception(string message, Action action, string fileName)
{
try
{
action();
}
catch (Exception ex)
{
InputLogger("代码段出现异常,信息为" + ex.Message, string.IsNullOrWhiteSpace(fileName)
? "Exception" + _defaultLoggerName
: fileName);
}
} public void Logger_Exception(string message, Action action)
{
Logger_Exception(message, action, null);
} public void Logger_Info(string message)
{
InputLogger(message, null);
} public void Logger_Info(string message, string fileName)
{
InputLogger(message, string.IsNullOrWhiteSpace(fileName)
? "Logger" + _defaultLoggerName
: fileName);
} #endregion
}

三 模版方式模式规定具体流程,抽象个性化方法

对于个性化的操作声明为抽象方法,在基类中实现统一的操作流程,在各个派生类中去实现个性化的模块,这正是模版方式模式的体现

aaarticlea/png;base64,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" alt="" />

四 策略模式以多种方式实现某个功能

对于文件持久化的方式有很多,而你可以分别去实现它,不知不觉中,我们正在使用策略模式来开发应用程序

普通持久化

    /// <summary>
/// 以普通的文字流的方式写日志
/// </summary>
internal class NormalLogger : LoggerBase
{
protected override void InputLogger(string message, string fileName)
{
string filePath = FileUrl + (fileName ?? "logger.log");
string dir = filePath.Substring(, filePath.LastIndexOf("\\"));
if (!System.IO.Directory.Exists(dir))
{
System.IO.Directory.CreateDirectory(dir);
}
using (System.IO.StreamWriter srFile = new System.IO.StreamWriter(filePath, true))
{
srFile.WriteLine(message);
srFile.Close();
srFile.Dispose();
}
}
}

log4net实现日志分级的持久化

 /// <summary>
/// Function:以log4net组件的方式写日志
/// Remark:日志记录方法可以使用第三方组件,如log4net
/// Author:zhangzhanling
/// Blogs:www.cnblogs.com/lori
/// </summary>
internal class Log4Logger : LoggerBase
{
/// <summary>
/// log4net配置文件路径
/// </summary>
static string _logConfig = System.Web.HttpContext.Current.Server.MapPath("/log4net.config"); static Log4Logger()
{
log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(_logConfig));
} #region Prviate Methods
/// <summary>
/// 写日志方法
/// </summary>
/// <param name="message"></param>
/// <param name="fileName"></param>
protected override void InputLogger(string message, string fileName)
{
string filePath = FileUrl + fileName;
var iLog = log4net.LogManager.GetLogger("Core.Logger");
ChangeLog4netLogFileName(iLog, filePath, message);
} private void ChangeLog4netLogFileName(log4net.ILog iLog, string filePath, string message)
{
log4net.Core.LogImpl logImpl = iLog as log4net.Core.LogImpl;
if (logImpl != null)
{
var ac = ((log4net.Repository.Hierarchy.Logger)logImpl.Logger).Appenders;
var rfa = ac[] as log4net.Appender.RollingFileAppender;
if (rfa != null)
{
string dir = filePath.Substring(, filePath.LastIndexOf("\\"));
if (!System.IO.Directory.Exists(dir))
{
System.IO.Directory.CreateDirectory(dir);
}
rfa.File = filePath;
// 更新Writer属性
rfa.Writer = new System.IO.StreamWriter(rfa.File, rfa.AppendToFile, rfa.Encoding);
rfa.Writer.WriteLine(message);
rfa.Writer.Close();
rfa.Writer.Dispose();
rfa.Close(); } }
} #endregion }

五 工厂模式动态生产对象,单例模式保持对象实例的唯一性

当我们以多种方式实现了对日志的持久化后,我们可以通过工厂模式动态的在这些持久化方式之间实现切换,对象实现单例之后,减少了内存开销,使对象的属性成为了全局性属性!

    /// <summary>
/// 日志生产类
/// Singleton模式和策略模式和工厂模式
/// </summary>
public class LoggerFactory : ILogger
{
/// <summary>
/// 对外不能创建类的实例
/// </summary>
private LoggerFactory()
{ string loggerType = System.Configuration.ConfigurationManager.AppSettings["LoggerType"] ?? "NormalLogger";
switch (loggerType)
{
case "NormalLogger":
iLogger = new NormalLogger();
break;
case "Log4Logger":
iLogger = new Log4Logger();
break;
default:
throw new ArgumentException("日志方法不正确,目前只支持NormalLogger和Log4Logger");
}
//(ILogger)Assembly.Load("Logger.Core").CreateInstance("Logger.Core." + className.Trim());
} #region Logger有多种实现时,需要使用Singleton模式 private static object lockObj = new object();
private static LoggerFactory instance = null;
private ILogger iLogger = null;
/// <summary>
/// Get singleton instance of IoCFactory
/// </summary>
public static LoggerFactory Instance
{
get
{
if (instance == null)
{
lock (lockObj)
{
if (instance == null)
{
instance = new LoggerFactory();
}
}
}
return instance;
}
} #endregion #region ILogger 成员 public void Logger_Timer(string message, Action action, string fileName)
{
iLogger.Logger_Timer(message, action, fileName);
} public void Logger_Timer(string message, Action action)
{
iLogger.Logger_Timer(message, action);
} public void Logger_Exception(string message, Action action, string fileName)
{
iLogger.Logger_Exception(message, action, fileName);
} public void Logger_Exception(string message, Action action)
{
iLogger.Logger_Exception(message, action);
} public void Logger_Info(string message)
{
iLogger.Logger_Info(message);
} public void Logger_Info(string message, string fileName)
{
iLogger.Logger_Info(message, fileName);
} #endregion
}

最后有一句话送给大家:坚持,其实就是一种胜利!

回到目录

我心中的核心组件(可插拔的AOP)~第十五回 我的日志组件Logger.Core(策略,模版方法,工厂,单例等模式的使用)的更多相关文章

  1. 我心中的核心组件(可插拔的AOP)~第五回 消息组件

    回到目录 之所以把发消息拿出来,完全是因为微软的orchard项目,在这个项目里,将公用的与领域无关的功能模块进行抽象,形成了一个个的组件,这些组件通过引用和注入的方式进行工作,感觉对于应用程序的扩展 ...

  2. 我心中的核心组件(可插拔的AOP)~第四回 异常拦截器

    回到目录 之前说过有关拦截器的文章,第二回  缓存拦截器,事实上,在那讲里说的最多是AOP和缓存组件,对于拦截的概念并没有详细的说明,这一讲,不说AOP,主要说一下拦截器,拦截器Interceptio ...

  3. 我心中的核心组件(可插拔的AOP)~第六回 消息组件~续

    回到目录 上一回写消息组件已经是很久之前的事了,这一次准备把消息组件后续的东西说一下,事实上,第一篇文章主要讲的是发消息,而这一讲最要讲的是收消息,简单的说,就是消息到了服务器之后,如何从服务器实时的 ...

  4. 我心中的核心组件(可插拔的AOP)~第十三回 实现AOP的拦截组件Unity.Interception

    回到目录 说在前 本节主要说一下Unity家族里的拦截组件,对于方法拦截有很多组件提供,基本上每个Ioc组件都有对它的实现,如autofac,它主要用在orchard项目里,而castle也有以拦截的 ...

  5. 我心中的核心组件(可插拔的AOP)~大话开篇及目录

    回到占占推荐博客索引 核心组件 我心中的核心组件,核心组件就是我认为在项目中比较常用的功能,如日志,异常处理,消息,邮件,队列服务,调度,缓存,持久化,分布式文件存储,NoSQL存储,IoC容器,方法 ...

  6. 我心中的核心组件(可插拔的AOP)~第二回 缓存拦截器

    回到目录 AOP面向切面的编程,也称面向方面的编程,我更青睐于前面的叫法,将一个大系统切成多个独立的部分,而这个独立的部分又可以方便的插拔在其它领域的系统之中,这种编程的方式我们叫它面向切面,而这些独 ...

  7. 我心中的核心组件(可插拔的AOP)~调度组件quartz.net

    回到目录 quartz.net是一个任务调度组件,它可以灵活的设置你的调试方式,按时间,按日期,按周期都可以很容易的实现,quartz不仅可以用在web中,而且还可以部署在winform,winser ...

  8. 我心中的核心组件(可插拔的AOP)~第十二回 IoC组件Unity

    回到目录 说在前 Ioc组件有很多,之前也介绍过autofac,castle等,今天再来说一下在微软Nlayer DDD架构里使用的unity组件,今天主要说一下依靠注入,如果希望看拦截的用法,可以阅 ...

  9. 我心中的核心组件(可插拔的AOP)~调度组件quartz.net续~任务管理器的开发

    回到目录 对于任务调度来说,越来越多的团队选择了quartz,它在java和.net环境下表现都十分优秀,配置简单,功能强大,时间表达式配置灵活,但在使用时,还是感觉缺点什么,怎么说,你在服务器上安装 ...

随机推荐

  1. NPOI创建DOCX常用操作【转】

    1.  创建文档 XWPFDocument m_Docx = new XWPFDocument();2.  页面设置 //1‘=1440twip=25.4mm=72pt(磅point)=96px(像素 ...

  2. 【九度OJ】题目1111:单词替换

    题目1111:单词替换 题目描述: 输入一个字符串,以回车结束(字符串长度<=100).该字符串由若干个单词组成,单词之间用一个空格隔开,所有单词区分大小写.现需要将其中的某个单词替换成另一个单 ...

  3. 基于 Winform + DotNetBar 写的股市行情助手

    StockViewer 股市行情助手 简介 观看股市行情,窗口太显眼,是否担心被身后的老板发现? 窗口来回切换,工作时每隔几分钟就要看一眼股市.难道只能同时做一件事情吗? 现在,一款完全免费.开源的小 ...

  4. rails4.2~devise邮箱测试

    1.由于网站无需验证,只需一封欢迎邮件,在config/intiailzers/devise.rb里面配置 config.allow_unconfirmed_access_for = nil #2.d ...

  5. [XAF] How to use the Allow/Deny permissions policy in the existing project

    https://www.devexpress.com/Support/Center/Question/Details/T418166 Clear [C#] using DevExpress.Persi ...

  6. Cookie与Session的区别-总结很好的文章

    Cookie与Session的区别-总结很好的文章 本文分别对Cookie与Session做一个介绍和总结,并分别对两个知识点进行对比分析,让大家对Cookie和Session有一个更深入的了解,并对 ...

  7. C++ REST SDK in Visual Studio 2013

    The C++ REST project provides a modern asynchronous C++ API for cloud-based client-server communicat ...

  8. Android性能优化典范第一季

    2015年伊始,Google发布了关于Android性能优化典范的专题,一共16个短视频,每个3-5分钟,帮助开发者创建更快更优秀的Android App.课程专题不仅仅介绍了Android系统中有关 ...

  9. Python札记 -- MongoDB模糊查询

    最近在使用MongoDB的时候,遇到了使用多个关键词进行模糊查询的场景.竹风使用的是mongoengine库. 查了各种资料,最后总结出比较好用的方法.先上代码,后面进行详细说明.如下: #!/usr ...

  10. MQTT协议简记

    MQTT - MQ Telemetry Transport   轻量级的 machine-to-machine 通信协议. publish/subscribe模式. 基于TCP/IP. 支持QoS. ...