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

  • 相关阅读:
    思念
    空白
    curl json string with variable All In One
    virtual scroll list All In One
    corejs & RegExp error All In One
    socket.io All In One
    vue camelCase vs PascalCase vs kebabcase All In One
    element ui 表单校验,非必填字段校验 All In One
    github 定时任务 UTC 时间不准确 bug All In One
    input range & color picker All In One
  • 原文地址:https://www.cnblogs.com/huyh/p/1434542.html
Copyright © 2011-2022 走看看