`
onaod32n
  • 浏览: 6662 次
社区版块
存档分类
最新评论

关于多功能日志记录组件的实现

 
阅读更多

  最近在思考通用组件库的设计。
  考虑到项目中一些功能的重复使用,需要将它们封装起来,做成组件的方式,提供代码的复用性。
  在公用组件的封装中,日志记录是比较典型的一个。通常日志记录的形式很多,但是在一个项目中的使用形式很单一。但是,现在的项目,需要提供多种日志记录的实现。记录进平面文件、记录进数据库,记录的时候根据业务不同,还有其他的区分等。
  设计的时候需要提供充分的可扩展性,以后有可能还要增加其他的记录形式。
  日志类的设计,采用的是策略模式:
  简单实现如下:
  抽象基类: namespace ConsoleApplication1 { public abstract class Logger { public virtual void Log() { Console.WriteLine("This is the base class's logger"); } } } 定义了一个虚方法Log
  文件记录类: namespace ConsoleApplication1 { internal class FileLogger : Logger { public override void Log() { Console.WriteLine("This is the file Logger"); } } } 继承了抽象基类,同时覆盖了基类的Log方法,提供了自己的实现。
  数据库记录类: namespace ConsoleApplication1 { internal class DBLogger:Logger { public override void Log() { Console.WriteLine("This is the DB Logger."); } } } 同上,不解释
  事件记录类: namespace ConsoleApplication1 { internal class EventLogger : Logger { public override void Log() { Console.WriteLine("This is the event logger"); } } } 可以看到这些子类的访问修饰符都定义为internal,也就是说,这些"算法"[沿袭策略模式的叫法,虽然有些不大恰当]没有就必要被组件外部访问。组件外部统一通过抽象类进行访问。
  很显然,这里出现了一系列的同级别的功能相似的派生类,我们可以用工厂来管理他们的创建。
  同时,我们想到面向对象的一个原则--开放封闭原则。也就是对扩展开放,对修改封闭。我们想要在修改的时候将改动的范围缩得越小越好。
  如果采用普通的静态工厂类,通过传递硬编码的字符串的标识来判断应该实例化哪个类的话。形如下实现方式: public static Logger CreateLoggerInstance_Old(string loggerType) { Logger myLogger = null; switch (loggerType) { case "File": myLogger = new FileLogger(); break; case "DB": myLogger = new DBLogger(); break; case "Event": myLogger = new EventLogger(); break; default: break; } return myLogger; } 那么我们要新增一个日志记录方案的改动就会非常多:
  1、你必须再去实现一个新的日志记录派生类,继承自Logger,去实现新的"算法"逻辑。
  2、修改如上类库的实例化派生类对象的方法,再增加一个新的case语句。
  3、当然客户端也得做出应变。
  其实,我们可以动态地将类型传递给实例化派生类对象的方法,这样就不需要采取上面的"匹配机制",简易实现如下:  public static Logger CreateLoggerInstance(string classNameForLogger) { Type loggerType = Type.GetType(classNameForLogger); if (loggerType!=null) { return Activator.CreateInstance(loggerType) as Logger; } return null; } 这样我们就永远也不用再来修改这个方法了。
  在客户端(调用端),我们可以将需要用到的不同的日志记录类的类型信息通过配置的方式配置在配置文件中。这样在新增一种日志记录方案的时候,改动就小得多。
  这里给出简易调用: namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Logger myLogger = LoggerFactory.CreateLoggerInstance("ConsoleApplica tion1.DBLogger"); myLogger.Log(); Logger newLogger = LoggerFactory.CreateLoggerInstance("ConsoleApplica tion1.EventLogger"); newLogger.Log(); Console.Read(); } } } 形如:"ConsoleApplication1.DBLogger"的字符串,一般都建议放在配置文件中。
  以上就是这个工具组件设计的构思,当然具体的记录实现都是封装的微软企业库中的Logging组件。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics