`
庄表伟
  • 浏览: 1150569 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

敲响OO时代的丧钟——新语言的威力(2)

阅读更多
ajoo的面向组合子的程序设计方法已经连载了八篇了,说实话,我一直在找他这方法中的漏洞,而且觉得有那么点意思,大概可以写点什么了。然后呢,我就想这么个问题,假设用DJ来实现一个logging的需求,该如何做呢?
 
想来想去,特别是在我仔仔细细的看过ajoo的CO代码之后,我突然顿悟了!我差点错过了一个极好的例子。当初ajoo发现,logging是一个说明CO程序设计方法的不可多得的好例子。而我发现,这个需求用DJ实现起来,甚至整个CO编程用DJ实现起来,都是易如反掌,如此好例子,我要是错过,岂不是太可惜了。因此,我在这里要郑重其事的向ajoo表示感谢,感谢他提供了这么好的例子,并且已经做了大量的工作,来解说这个例子。废话不多说了,下面开始我的代码。
contract Logger{
    public void println(LogEvent e);
    public void printException(Exception e);
}
这其中的LogEvent和Exception分别是DJ中的用户自定义类事件与异常类事件。与ajoo的代码有所差别。而这个差别,正是DJ更加方便之处。
datatype LogEvent as UserEvent{
    String msg;
}
在LogEvent的基础上,我们还可以定义更加具有说明性的Log,比如:
datatype LevelLogEvent as LogEvent{
    int level;
}
OK!我们接下来定义一个NopLogger:
channel NopLogger:Logger{
    public void println(LogEvent e){}
    public void printException(Exception e){}
}
再来一个WriterLogger:
channel WriterLogger<PrintWriter writer>:Logger{
    public void println(LogEvent e){
        writer.println(e.msg);
    } 
    public void printException(Exception e){ 
        writer.println(e.stackTrace);
    }
}
再来一个SequenceLogger:
channel SequenceLogger<contract Logger[] loggers>:Logger{
    public void (LogEvent e){
        foreach(l: loggers){
            l.println(e);
        }
    }
    public void printException(Exception e){
        foreach(l:loggers){
            l.printException(e);
        }
    }
}
再来一个FilteredLogger:
channel FilteredLogger<contract Logger logger1,contract Logger logger2>:Logger{
    public void println(LevelLogEvent e){
        if(e.level==ERROR)logger1.println(e);
        else logger2.println(e);
    }
    public void printException(LevelException e){
        if(e.level==ERROR) logger1.printException(e);
        else logger2.printException(e);
    }
}
再来一个IgnoringLogger:
channel IgnoringLogger<contract Logger logger1,contract Logger logger2>:Logger
    public void println(LevelLogEvent e){
        if(e.level>=ERROR)logger1.println(e);
        else logger2.println(e);
    }
    public void printException(LevelException e){
        if(e.level>=ERROR) logger1.printException(e);
        else logger2.printException(e);
    }
}
我不打算再抄ajoo的代码了,似乎是“有点无赖”了。再说,为了说明我的DJ能够很好的描述组合子,这些channel定义也就够了。接着说怎么装配。
 
DJ中的channel,并不是独立存在,而是要和DynamicObject协同工作的。在一个DynamicObject中,既包含数据区,也包含Channel组。所有插入一个动态对象的channel,都可以定义事件处理部分,以接收可能发生的事件。而需要记录log的事件,可以由任何一个channel中的任何一段代码,以如下代码方式抛出:
throw new UserEvent("Logging Message ......");
至于这个事件,将被如何处理,抛出事件的代码是无需关心的。至于接收log事件的channel,可以如下定义:
channel LoggerChannel<datatype <T> data,contract Logger log>{
event:
    onEvent(LogEvent e){
        log.println(e);
    }
    onEvent(Exception e){
        log.printException(e);
    }
}
各位,有没有体会到DJ这个语言的威力呢?我们可以将Log与Exception分开处理,比如:
channel LoggerChannel<datatype <T> data,contract Logger log>{
event:
    onEvent(LogEvent e){
        log.println(e);
    }
}
 
channel ExceptionChannel<datatype <T> data,contract Logger log>{
event:
    onEvent(Exception e){
        log.printException(e);
    }
}
然后,这两个Channel我可以以不同的方式组装,完全没有相互的干扰......
 
今天的代码已经写得太多了,大家先体会体会吧。明天再接着写DJ能够做到,而CO很困难的其他Loggin需求。
 
(未完待续)
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics