什么是流利语法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 Evans和MartinFowler创造)是面向对象的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# 使用fluent在LINQ中广泛编程来生成使用标准查询运算符的查询。基于扩展方法.
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} \nlast name: {1} \nsex: {2} \naddress: {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
什么是流利语法Fluent Syntax的更多相关文章
- ES7: 展开语法spread syntax:
第一次遇到: payload = {...payload, manufacturer: state.manufacturers.filter(x => x._id === payload.man ...
- shell脚本启动语法错误syntax error near unexpected token '{
执行shell脚本时失败,报语法错误,但脚本内容检查正常 原因为该脚本是在非Linux系统下编辑之后放到系统执行的,文件模式类型非Linux系统匹配的模式类型. 查看文件的模式类型 显示文件的模式类型 ...
- Es6扩展运算符--三点运算符(...)--展开语法(Spread syntax)
0.看文档呀 关于拓展运算符更详细的解释见 > MDN展开语法 关于剩余参数更详细的解释见 >MDN剩余参数 关于解构赋值更详细的解释见 >MDN解构赋值 直接看上面的文档更好 1. ...
- 高速上手Unity中最好的补间动画插件DFTween
出处:http://blog.csdn.net/u010019717 author:孙广东 时间:2015.3.17 23:00 DFTween 是一个在 Unity 游戏引擎中高 ...
- LINQ 学习路程 -- 查询语法 LINQ Query Syntax
1.查询语法 Query Syntax: from <range variable> in <IEnumerable<T> or IQueryable<T> ...
- LINQ教程二:LINQ操作语法
LINQ查询时有两种语法可供选择:查询表达式语法(Query Expression)和方法语法(Fluent Syntax). 一.查询表达式语法 查询表达式语法是一种更接近SQL语法的查询方式. L ...
- LINQ之路 4:LINQ方法语法
书写LINQ查询时又两种语法可供选择:方法语法(Fluent Syntax)和查询语法(Query Expression). LINQ方法语法是非常灵活和重要的,我们在这里将描述使用链接查询运算符的方 ...
- Linq学习(主要参考linq之路)----2LINQ方法语法
方法语法:Fluent Syntax 方法语法是非常灵活和重要的.我们这里讲描述使用连接查询运算符的方式来创建复杂的子查询,方法语法的本质是通过扩展方法和Lambda表达式来创建查询. eg1: st ...
- C#语法之Linq查询基础一
Linq做.Net开发的应该都用过,有些地方很复杂的逻辑用Linq很方便的解决.对于Linq to object.Linq to xml.Linq to sql.Linq to Entity(EF)都 ...
随机推荐
- C语言实现通用数据结构的高效设计
近期在阅读一个开源的C++代码.里面用到了大量的STL里面的东西.或许是自己一直用C而非常少用C++来实现算法的原因.STL里面大量的模板令人心烦.一直对STL的效率表示怀疑,但在网上搜到这样一个帖子 ...
- MySQL分区技术 (一)
4:MySQL 分区技术(是mysql 5.1以版本号后開始用->是甲骨文mysql技术团队维护人员以插件形式插入到mysql里面的技术) 眼下,针对海量数据的优化主要有2中方法: 1:大表拆成 ...
- 从零開始学android<Menu菜单组件.三十.>
在Android系统之中.菜单一共同拥有三类:选项菜单(OptionsMenu).上下文菜单(ContextMenu)和子菜单(SubMenu). 今天我们就用几个样例来分别介绍下菜单的使用 acti ...
- Xcode 4.6.2 运行次数为偶数程序崩溃问题
如果你的MAC 系统升级到10.8.4 Xcode升级到4.6.2,在工程运行第二次.第四次.第六次 ... 的时候程序就会崩溃 无论是新建的模板工程也会这样,这个属于系统BUG,在stackove ...
- c#常见stream操作
原文: c#常见stream操作 常见并常用的stream一共有 文件流(FileStream), 内存流(MemoryStream), 压缩流(GZipStream), 加密流(CrypToStre ...
- OCP读书笔记(5) - 使用RMAN创建备份
5.Creating Backups with RMAN 创建备份集 RMAN> backup as backupset format '/u01/app/oracle/backup/rmanb ...
- 《TCP/IP作品详细解释2:实现》笔记--Radix树路由表
通过IP完整的路由是路由机制,它通过搜索路由表来确定从哪个分组被发送的接口执行此,它是不一样的路由策略,路由策略 它是一组规则,这些规则可以被用来确定哪些路由编程到路由表,Net/3内核实现的路由机制 ...
- hdu4521(线段树+dp)
传送门:小明系列问题——小明序列 题意:有n个数,求间距大于d的最长上升序列. 分析:dp[i]表示在i点以a[i]结束距离大于d的最长上升序列,然后每更新到第i点时,取i-d之前小于a[i]的数为结 ...
- hdu2062(递推)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2062 详细分析:http://mamicode.com/info-detail-95273.html ...
- UVA 11100 The Trip, 2007 贪心(输出比较奇葩)
题意:给出n个包的大小,规定一个大包能装一个小包,问最少能装成几个包. 只要排序,然后取连续出现次数最多的数的那个次数.输出注意需要等距输出. 代码: /* * Author: illuz <i ...