zoukankan      html  css  js  c++  java
  • 什么是流利语法Fluent Syntax

    

    出处:http://blog.csdn.net/u010019717

    author:孙广东      时间:2015.3.18   23:00


    编程新概念:什么是流利语法fluent syntax
    首先感谢 unity的一款插件 DFTween (内容例如以下http://blog.csdn.net/u010019717/article/details/44359119,通过学习它知道了流利语法的概念。

    Fluent interface连贯接口

    在软件project,一种Fluent interface连贯接口(作为首先由Eric EvansMartinFowler创造)是面向对象的API,旨在提供更具可读性的代码运行。

            Fluent interface通常通过使用methodcascading方法级联(具体methodchaining方法链接)context指令连续调用运行 (但Fluent interface须要不不过方法链接)。通常context上下文是

    ·定义通过返回值(类对象)调用方法

    ·以自我作为參照,在新的背景下是相当于最后一个context上下文

    ·通过返回一个void的上下文终止。

    内容

    1 History

    2 Examples

    2.1 JavaScript

    2.2 Java

    2.3 C++

    2.7 PHP

    2.8 C#

    2.9 Python

    历史

    术语"Fluent interface"是在 2005 年年底提出,尽管这样的interface面的总体风格追溯到 1970 年代,Smalltalk 在级联的方法被发明,在上世纪 80 年代的很多样例。最熟悉的是在 c + +,使用iostream<<>> 运算符为消息传递、将多个数据发送到同一个对象和其它方法调用同意"manipulators"

     样例

    JavaScript

    有非常多使用几种变体的 JS 库的样例:可能是最广为人知的 jQuery。通经常使用fluent builders流利的建设者来实现 'DB 查询',比如https://github.com/Medium/dynamite :

    // getting an item from a table
    
    client.getItem('user-table')
    
        .setHashKey('userId', 'userA')
    
        .setRangeKey('column', '@')
    
        .execute()
    
        .then(function(data) {
    
            // data.result: the resulting object
    
        })
    
    
    

    简单的办法做到这一点在 javascript 中使用prototype inheritance原型继承和 this

    // example from http://schier.co/post/method-chaining-in-javascript
    
    // define the class
    
    var Kitten = function() {
    
      this.name = 'Garfield';
    
      this.color = 'brown';
    
      this.gender = 'male';
    
    };
    
     
    
    Kitten.prototype.setName = function(name) {
    
      this.name = name;
    
      return this;
    
    };
    
     
    
    Kitten.prototype.setColor = function(color) {
    
      this.color = color;
    
      return this;
    
    };
    
     
    
    Kitten.prototype.setGender = function(gender) {
    
      this.gender = gender;
    
      return this;
    
    };
    
     
    
    Kitten.prototype.save = function() {
    
      console.log(
    
        'saving ' + this.name + ', the ' +
    
        this.color + ' ' + this.gender + ' kitten...'
    
      );
    
     
    
      // save to database here...
    
     
    
      return this;
    
    };
    
     
    
    // use it
    
    new Kitten()
    
      .setName('Bob')
    
      .setColor('black')
    
      .setGender('male')
    
      .save();

    更通用的方式做到这一点是在mu-ffsm中实现.

    var mkChained = function(spec) {
    
      return function(init) {
    
        var s = spec[0] ? spec[0](init) : 0;
    
     
    
        var i = function(opt) {
    
          return spec[1] ? spec[1](s, opt) : s;
    
        }
    
     
    
        Object.keys(spec).forEach(
    
          function(name){
    
            // skip `entry` and `exit` functions
    
            if(/^d+$/.test(name))
    
              return;
    
     
    
            // transition 'name : (s, opt) -> s'
    
            i[name] = function(opt) {
    
              s = spec[name](s, opt);
    
              return i;
    
            };
    
        });
    
     
    
        return i;
    
      }
    
    };
    
     
    
    var API = mkChained({
    
      0:    function(opt)    {return ;/* create initial state */},
    
      then: function(s, opt) {return s; /* new state */},
    
      whut: function(s, opt) {return s; /* new state */},
    
      1:    function(s, opt) {return ;/* compute final value */}
    
    });
    
     
    
    // We create an instance of our newly crafted API,
    
    var call = API() // entry
    
       .whut()       // transition
    
       .then()       // transition
    
       .whut();      // transition
    
     
    
    // And call it
    
    var result0 = call() // exit
    
      , result1 = call() // exit

    Java

    JOOQ型号的库作为 fluent API Java 中的 SQL

    Author a = AUTHOR.as("a");
    
    create.selectFrom(a)
    
          .where(exists(selectOne()
    
                       .from(BOOK)
    
                       .where(BOOK.STATUS.eq(BOOK_STATUS.SOLD_OUT))
    
                       .and(BOOK.AUTHOR_ID.eq(a.ID))));

    Op4j库使fluent流畅代码,用于运行辅助任务结构迭代、 数据转换、 过滤等。

    String[] datesStr = new String[] {"12-10-1492", "06-12-1978"};
    
    ...
    
    List<Calendar> dates = 
    
        Op.on(datesStr).toList().map(FnString.toCalendar("dd-MM-yyyy")).get();

    Fluflu凝视处理器能够使用 Java 凝视 fluent API创建。

    JaQue使 Java 8 lambda 时必须表示为表达式文件夹树在运行时,使它能够即创建类型安全连贯接口,而不是窗口中的对象:

    Customer obj = ... 
    
    obj.property("name").eq("John")
    
     
    
    一种学法:
    
    method<Customer>(customer -> customer.getName() == "John")

    C + +

    C + +中,一个fluentinterface常见用途是的标准iostream,当中链重载的运算符.

    以下是提供在更传统的界面,在 c + + 中的fluent interface包装程序的演示样例:

     

    // Basic definition
    
     class GlutApp { 
    
     private:
    
         int w_, h_, x_, y_, argc_, display_mode_;
    
         char **argv_;
    
         char *title_;
    
     public:
    
         GlutApp(int argc, char** argv) {
    
             argc_ = argc;
    
             argv_ = argv;
    
         }
    
         void setDisplayMode(int mode) {
    
             display_mode_ = mode;
    
         }
    
         int getDisplayMode() {
    
             return display_mode_;
    
         }
    
         void setWindowSize(int w, int h) {
    
             w_ = w;
    
             h_ = h;
    
         }
    
         void setWindowPosition(int x, int y) {
    
             x_ = x;
    
             y_ = y;
    
         }
    
         void setTitle(const char *title) {
    
             title_ = title;
    
         }
    
         void create(){;}
    
     };
    
     // Basic usage
    
     int main(int argc, char **argv) {
    
         GlutApp app(argc, argv);
    
         app.setDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_ALPHA|GLUT_DEPTH); // Set framebuffer params
    
         app.setWindowSize(500, 500); // Set window params
    
         app.setWindowPosition(200, 200);
    
         app.setTitle("My OpenGL/GLUT App");
    
         app.create();
    
     }
    
     
    
     // Fluent wrapper
    
     class FluentGlutApp : private GlutApp {
    
     public:
    
         FluentGlutApp(int argc, char **argv) : GlutApp(argc, argv) {} // Inherit parent constructor
    
         FluentGlutApp &withDoubleBuffer() {
    
             setDisplayMode(getDisplayMode() | GLUT_DOUBLE);
    
             return *this;
    
         }
    
         FluentGlutApp &withRGBA() {
    
             setDisplayMode(getDisplayMode() | GLUT_RGBA);
    
             return *this;
    
         }
    
         FluentGlutApp &withAlpha() {
    
             setDisplayMode(getDisplayMode() | GLUT_ALPHA);
    
             return *this;
    
         }
    
         FluentGlutApp &withDepth() {
    
             setDisplayMode(getDisplayMode() | GLUT_DEPTH);
    
             return *this;
    
         }
    
         FluentGlutApp &across(int w, int h) {
    
             setWindowSize(w, h);
    
             return *this;
    
         }
    
         FluentGlutApp &at(int x, int y) {
    
             setWindowPosition(x, y);
    
             return *this;
    
         }
    
         FluentGlutApp &named(const char *title) {
    
             setTitle(title);
    
             return *this;
    
         }
    
         // It doesn't make sense to chain after create(), so don't return *this
    
         void create() {
    
             GlutApp::create();
    
         }
    
     };
    
     // Fluent usage
    
     int main(int argc, char **argv) {
    
         FluentGlutApp(argc, argv)
    
             .withDoubleBuffer().withRGBA().withAlpha().withDepth()
    
             .at(200, 200).across(500, 500)
    
             .named("My OpenGL/GLUT App")
    
             .create();
    
     }

    PHP

    PHP 中,一个人能够通过使用$this 特殊的变量所表示的实例返回当前对象。因此返回 $this ;将使返回的实例的方法。以下的演示样例定义一个类Employee和三种方法来设置其name, surname salary。每一个返回Employee类同意对链方法的实例。

    <?php
    
    class Employee
    
    {
    
        public $name;
    
        public $surName; 
    
        public $salary;
    
        public function setName($name)
    
        {
    
            $this->name = $name;
    
            return $this;
    
        }
    
        public function setSurname($surname)
    
        {
    
            $this->surName = $surname;
    
            return $this;
    
        }
    
        public function setSalary($salary)
    
        {
    
            $this->salary = $salary;
    
            return $this;
    
        }
    
        public function __toString()
    
        {
    
            $employeeInfo = 'Name: ' . $this->name . PHP_EOL;
    
            $employeeInfo .= 'Surname: ' . $this->surName . PHP_EOL;
    
            $employeeInfo .= 'Salary: ' . $this->salary . PHP_EOL;
    
            return $employeeInfo;
    
        }
    
    }
    
    # Create a new instance of the Employee class:
    
    $employee = new Employee();
    
    # Employee Tom Smith has a salary of 100:
    
    echo $employee->setName('Tom')
    
                  ->setSurname('Smith')
    
                  ->setSalary('100');
    
    # Display:
    
    # Name: Tom
    
    # Surname: Smith
    
    # Salary: 100

     

    C#

    C# 使用fluentLINQ中广泛编程来生成使用标准查询运算符的查询。基于扩展方法.

    var translations = new Dictionary<string, string>
    
                       {
    
                           {"cat", "chat"},
    
                           {"dog", "chien"},
    
                           {"fish", "poisson"},
    
                           {"bird", "oiseau"}
    
                       };
    
    // Find translations for English words containing the letter "a",
    
    // sorted by length and displayed in uppercase
    
    IEnumerable<string> query = translations
    
             .Where   (t => t.Key.Contains("a"))
    
             .OrderBy (t => t.Value.Length)
    
             .Select  (t => t.Value.ToUpper());
    
     
    
    // The same query constructed progressively:
    
    var filtered   = translations.Where (t => t.Key.Contains("a"));
    
    var sorted     = filtered.OrderBy   (t => t.Value.Length);
    
    var finalQuery = sorted.Select      (t => t.Value.ToUpper());
    
     
    
    Fluent interface也能够用于链设置方法,当中operates/shares同样的对象。而不是创建一个customer类我们能够创建一个data context数据上下文,能够用fluent interface,例如以下所看到的:
    
      
    
    //defines the data context
    
    class Context
    
        {
    
            public string fname { get; set; }
    
            public string lname {get; set;}
    
            public string sex { get; set; }
    
            public string address { get; set; }
    
        }
    
     
    
    //defines the customer class
    
        class Customer
    
        {
    
            Context context = new Context(); //initializes the context
    
            // set the value for properties
    
            public Customer FirstName(string firstName)
    
            {
    
                context.fname = firstName;
    
                return this;
    
            }
    
            public Customer LastName(string lastName)
    
            {
    
                context.lname = lastName;
    
                return this;
    
            }
    
            public Customer Sex(string sex)
    
            {
    
                context.sex = sex;
    
                return this;
    
            }
    
            public Customer Address(string address)
    
            {
    
                context.address = address;
    
                return this;
    
            }
    
            //prints the data to console
    
            public void Print()
    
            {
    
                Console.WriteLine("first name: {0} 
    last name: {1} 
    sex: {2} 
    address: {3}",context.fname,context.lname,context.sex,context.address);
    
            }
    
        }
    
        class Program
    
        {
    
            static void Main(string[] args)
    
            {
    
                //object creation
    
                Customer c1 = new Customer();
    
                //using the method chaining to assign & print data with a single line
    
                c1.FirstName("vinod").LastName("srivastav").Sex("male").Address("bangalore").Print();
    
            }
    
        }

    Python

    Python 返回 'self' 中的实例方法是实现fluent pattern的一种方法。

    class Poem(object):
    
        def __init__(self, content):
    
            self.content = content
    
     
    
        def indent(self, spaces):
    
            self.content = " " * spaces + self.content
    
            return self
    
     
    
        def suffix(self, content):
    
            self.content = self.content + " - " + content
    
            return self
    
     
    
    Poem("Road Not Travelled").indent(4).suffix("Robert Frost").content
    
     '    Road Not Travelled - Robert Frost'

    更具体的内容观看维基百科:https://en.wikipedia.org/wiki/Fluent_interface

    
  • 相关阅读:
    第一次程序改错
    趣拼图——项目演示及代码
    数据流图和数据流程图
    UML图
    UML用例图
    第二次迭代目标的分配
    小组分工
    迭代目标
    我们的项目
    2017-4-18 关于小组APP
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4512727.html
Copyright © 2011-2022 走看看