流畅接口是由Martin Fowler和Eric Evans创造的,流畅API意味着你构建一个API需要遵循以下要点:

1.API用户能够容易理解API

2.API为完成一个任务能够执行一系列动作,比如Java中可以看成是一系列方法调用,方法链。

3.每个方法名称应该是与业务领域相关的专门术语

4.API应该能提示指导API用户下一步用什么,以及某个时刻用户可能采取的操作。

假设你要设计一个业务域的API,比如是零售行业,那么应该有一些零售领域存在的共同的术语 ,在一定情境(任务)或上下文下,应该会采取一系列行动来完成这项任务或上下文情境。比如说,一张发票的生成必须遵循一定的步骤。

现在,当你设计一个API接口时,设计方式是:当用户调用计费服务用于发票生成时,用户可以流利地执行每一步,以完成发票的生成,API会帮助用户对计费服务调用步骤的执行。

当一个API方法被用户调用时,该方法将执行其任务并返回一个对象,这将有助于指导用户下一步该做什么-直到所有步骤执行。不同于一个标准API,它是使用一个连续的方式调用API的方法,以便成功完成一个任务。因此,API用户必须非常了解服务的步骤(服务的方法)。

案例:假设我们为一个餐馆设计一个API,作为餐馆客户,他会执行以下动作步骤:

1.用户进入餐馆

2.查询价目选择菜单

3.订餐

4.吃饭

5.付费。

在标准的API(非流畅API)设计中,会如下做法:

1.创建一个“餐厅”界面。

2.创建一个餐厅实现类。组成菜单类menucard。

3.创造餐厅属性名称,包括getter和setter等方法。

4.在menucard类中,有条目列表。暴露的一些方法,如showmenu(), ordermenu(),等。

5.每个条目都有名称和成本等特性以及相应的getter和setter。

6.当用户调用这个API的API,他/她会调用一个方法序列(进入餐厅,调用showmenu(),然后调用ordermenu(),等)。完成上述客户步骤。

上面这张设计不是流畅的,完成一项任务需要很多顺序语句执行,API用户必须了解这些顺序。

看看流畅API设计:

1.创建一个接口iresturant,有两种方法A.

2.打印餐厅名字,注意 返回类型 返回自身,因为在显示名称以后,用户希望看到的菜单。

3. show()方法返回menucard。

(这里暗示有两种方法:一是名字和另一个show(下一个操作用户要执行的)

4. IMENU有4个重要的方法showmenu():order(),eat(),pay(),所有方法返回menuhandler实现,所以我们可以执行这些动作中的一个。这是再次暗示。

Java代码:

package com.example.fluentapi.contract;
public interface IResturant {
public IResturant name(String name);
public IMenu show();
}
package com.example.fluentapi.contract;
public interface IMenu{
public IMenu order(int index);
public IMenu eat();
public IMenu pay();
public IItem get(int index);
}
package com.example.fluentapi.contract;
public interface IItem {
public IItem name();
public Integer cost();
}
实现:
package com.example.fluentapi.impl;
import com.example.fluentapi.contract.IMenu;
import com.example.fluentapi.contract.IResturant;
public class Arsalan implements IResturant{
String name;
String IMenu;
public IResturant name(String name) {
this.name=name;
System.out.println("Enter to hotel :: "+ name);
return this;
}
public IMenu show() {// TODO Auto-generated method stubArsalanMenuHandler handler = new ArsalanMenuHandler();
handler.showMenu();
return handler;
}
}
package com.example.fluentapi.impl;
import java.util.ArrayList;
import java.util.List;
import com.example.fluentapi.contract.IItem;
import com.example.fluentapi.contract.IMenu;
public class ArsalanMenuHandler implements IMenu{
List menuList = new ArrayList();
List selectedList = new ArrayList();
public ArsalanMenuHandler()
{
IItem biriyani = new IItem(){
public IItem name()
{
System.out.println("Mutton Biriyani");
return this;
}
public Integer cost()
{
return 180;
}
};
IItem muttonChap = new IItem(){
public IItem name()
{
System.out.println("Mutton Chap");
return this;
}
public Integer cost()
{
return 160;
}
};
IItem firni = new IItem(){
public IItem name()
{
System.out.println("Firni");
return this;
}
public Integer cost()
{
return 100;
}
};
menuList.add(biriyani);
menuList.add(muttonChap);
menuList.add(firni);
}
public IMenu order(int index) {// TODO Auto-generated method stubIItem item (index);
selectedList.add(item);
System.out.println("Order given ::");
item.name();
return this;
}
public IMenu eat() {
for(IItem item : selectedList)
{
System.out.println("eating ");
item.name();
}
return this;
}
public IMenu pay() {
int cost=0;
for(IItem item : selectedList)
{
cost = cost + item.cost();
}
System.out.println("Paying Rupees"+ cost);
return this;
}
@Override
public IItem get(int index) {// TODO Auto-generated method stubif(index <3)
{
return menuList.get(index);
}
return null;
}
public void showMenu(){
System.out.println("MENU IN ARSALAN");
for(IItem item : menuList)
{
item.name();
}
}
}

测试:

package com.example.fluentapi.impl;
public class FluentApiTest {
publicstaticvoid main(String[] args) {
new Arsalan().name("ARSALAN").show().order(0).order(1).eat().pay();
}
}

输出:

Enter to hotel :: ARSALAN
MENU IN ARSALAN
Mutton Biriyani
Mutton Chap
Firni
Order given ::
Mutton Biriyani
Order given ::
Mutton Chap
eating
Mutton Biriyani
eating
Mutton Chap
Paying Ruppes340

我们是通过下面方法链实现流畅调用的:

new Arsalan().name("ARSALAN").show().order(0).order(1).eat().pay();