zoukankan      html  css  js  c++  java
  • 从一个小实例开始 Boo开篇

    前一阵小组内部培训时,提到下面这个例子:
    “假设我们有个高档的热水器,我们给它通上电,当水温超过95度的时候:
    1、警报器会开始发出语音,告诉你水的温度;
    2、显示器也会改变水温的显示,提示水已经快烧开了。 ”

    相信大家能很快明白这是GoF设计模式中典型的Observer模式,下面我想通过这个例子用Boo实现来作为Boo系列的开篇。

    在继续之前,为了方便大家看到C#与Boo两者在语法上的不同,我先写出C#下Observer模式的实现(采用事件机制):

    #region C# Observer Pattern
    public delegate void NotifyEventHandler(Heater heater);
    
    public class Heater
    {
        public event NotifyEventHandler Notify = delegate { };
        public int Temperature {
            get;
            set;
        }
        public void Boil() {
            if (Temperature > 95)
                Notify(this);
        }
    }
    
    public abstract class Device
    {
        public virtual void Update(Heater heater) {
            Do();
            Console.WriteLine("The water is boiling! Water temperature is {0}", heater.Temperature);
        }
        protected abstract void Do();
    }
    public class Alarm : Device
    {
        protected override void Do() {
            Console.WriteLine("Alarm!");
        }
    }
    public class Monitor : Device
    {
        protected override void Do() {
            Console.WriteLine("Monitor!");
        }
    }
    #endregion

    这里我暂且不介绍Boo,而是直接给出Boo版本下的Observer模式:

    namespace Observer
    import System
    // Boo Observer Pattern
    //callable NotifyEventHandler(heater as Heater);
    class Heater:
     //event Notify as NotifyEventHandler
     event Notify as callable(object)
     
     [Property(Temperature)]
     _temperature as int
     
     def Boil():
    //  if Temperature > 95:
    //   Notify(self)
      Notify(self) if Temperature > 95 // Equivalent of the above
    //
    abstract class Device:
     virtual def Update(heater as Heater):
      Do()
      print "The water is boiling! Water temperature is ${heater.Temperature}."
     abstract def Do():
      pass
    
    class Alarm(Device):
     override def Do():
      print "Alarm!"
    class Monitor(Device):
     override def Do():
      print "Monitor!" 
    //
    heater = Heater(Temperature:98)
    alarm = Alarm()
    monitor = Monitor()
    //heater.Notify += def(heater as Heater):
    // print heater.Temperature
    heater.Notify += alarm.Update
    heater.Notify += monitor.Update
    
    heater.Boil()
    
    Console.ReadKey()
    

    Boo是一个类似Python语法、静态类型、运行在CLR之上的面向对象语言。它有一个强大的编译器扩展能力和更容易构建DSL的特性,目前Boo主要应用在DSL上。

    Boo的编译器扩展性意味着你可以对编译器进行自定义的扩展,使你能够在编译器层次上对Boo进行加强,这也使得Boo非常适合于DSL的编写。Boo编译器允许你直接与Pipeline管道交互,Boo编译器管道由一系列的Compiler steps组成,每个Compiler Step都可以与解析后的代码交互从而改变其AST(Abstract Syntax Tree),最终AST会生成.NET程序集代码(IL)。

    大家可以看看大师Ayende Rahien使用Boo写的例子,大家可以感受到Boo语言的灵活与强大:

    namespace BSDLiB
    
    import System
    import System.Xml
    import System.Threading
    import AstModifications
    import AstModifications.MetaMethods
    import AstModifications.SLA
    import AstModifications.SLA.MyExtensions
    
    import Boo.Lang.Compiler.Ast
    
    unroll i, 5:
     print i
     
    unroll2 i, 5:
     print i 
    
    print "Using XML OBject"
    print " - - - - - - - - - "
    xml = """
    <People>
     <Person>
      <FirstName>John</FirstName>
     </Person>
     <Person>
      <FirstName>Jane</FirstName>
     </Person>
    </People>
    """
    
    xmlDocument = XmlDocument()
    xmlDocument.LoadXml(xml)
    
    doc = XmlObject(xmlDocument.DocumentElement)
    for person as XmlObject in doc.Person:
     print person.FirstName
    
    print " - - - - - - - - - "
    print "Using meta methods"
    print " - - - - - - - - - "
    # Using Meta Methods
    try:
     verify 1 == 2
    except e:
     print e
     
    # Using macros
    print " - - - - - - - - - "
    print "Using Macros"
    print " - - - - - - - - - "
    limitedTo 200.ms:
       Thread.Sleep(201)
       whenExceeded:
                print "Took more than 200 ms!"
    
    
    #using AST Attributes
    print " - - - - - - - - - "
    print "Using AST Attributes"
    print " - - - - - - - - - "
    customer = Customer("test")
    
    try:
     customer.SetName(null)
    except e:
     print e

    【注】:
    1, unroll/unroll2
    是Boo中的Macro,用两种不同的方式实现了Macro。Boo中的Macro允许我们后期通过[macro name]来引用宏代码。
    2, XmlObject
    是实现了IQuackFu接口的类,IQuackFu接口可以让类自己负责方法、属性的调用,非常适合处理“Missing Method”的问题。
    3, verify
    Meta方法,标记了Meta属性的静态方法可以很容易对AST节点进行操作(Static methods tagged with the Meta attribute should be perceived as a shortcut to the compiler that accepts AST (Abstract Syntax Tree) Nodes and returns an AST node.),这个特性使之很容易创建新的keywords。
    4, limitedTo
    较复杂的Macro使用:两个Macro之间的交互、Extension的使用。

    例子中的具体特性以后我会慢慢向大家讲解,这里只是展示一下Boo的强大扩展性。

    借助于Boo所内建的语言特性以及简单的语法结构,加上其静态特性,我们可以用该语言更加高效地编写.NET应用程序。另外,在Boo中,我们还可以使用任何CLI平台上的现存类库,Boo代码同样能够容易地在其他CLI语言中被重用!稍后我会分几部分来详细介绍Boo语言以及其在C#中的使用(DSL方面)。

    最后,顺便也试试把JavaScript版本的Observer写出来:

    // JavaScript Observer Pattern
    function Heater(t) {
        this.Temperature = t;
    }
    Heater.prototype = {
        Notify: function() {
            if (this.events) {
                if (this.Temperature > 95) {
                    for (var i = 0; i < this.events.length; i++)
                        this.events[i].Update();
                }
            }
        },
        Attach: function(handler) {
            if (!this.events) this.events = [];
            this.events.push(handler);
        }
    }
    // Base class
    var Device = {
        Initialize: function(name) {
            this.Name = name;
        },
        Update: function() {
            alert(this.Name);
        }
    }
    // subclasses
    function Alarm(name) {
        Device.Initialize.call(this, name);
    }
    Alarm.prototype = Device;
    
    function Monitor(name) {
        Device.Initialize.call(this, name);
    }
    Monitor.prototype = Device;
    
    // The example
    var alarm = new Alarm("Alarm");
    var monitor = new Monitor("Monitor");
    var heater = new Heater(98);
    
    heater.Attach(alarm);
    heater.Attach(monitor);
    
    heater.Notify();

    大家有兴趣可以参考下面链接看看Boo的介绍,这会增加对Boo的认识很有帮助,稍后我会分几个部分循序渐进地向大家展现Boo的魅力,希望能有更多的人关注Boo,大家一起学习使用:
    Boo Website
    The Boo extensibility tutorials
    Ayende Rahien - Boo
    在CLR之上的构建领域特定语言
    概览CLI之上的新语言 - Boo

  • 相关阅读:
    Vector成员为指针时要注意的问题
    (转)C++中的static关键字的总结
    (转)内联(inline)函数与虚函数(virtual)的讨论
    基类类型和派生类型之间的转换以及虚函数
    (转) vector的reserve和resize
    关于函数返回值的一些见解
    (转)感受异或的神奇
    一个mysql不解的问题
    获取本机TCP连接状态信息
    (转)socket的SYN_RECV和ESTABLISHED状态
  • 原文地址:https://www.cnblogs.com/huyh/p/1434542.html
Copyright © 2011-2022 走看看