什么是流畅的界面?我找不到一个好的定义,但我得到的只是我不熟悉的语言中的长代码示例(例如C ++)。
另外,什么是漏洞抽象?
由于
答案 0 :(得分:26)
流畅的界面是一种API,允许您编写与普通英语大致相同的代码。例如:
Find.All.Questions(Where.IsAnswered == true);
方法链通常用作实现的一部分,但除此之外还有更多内容。引用Fowler:
我也注意到了一个常见的误解 - 许多人似乎将流畅的界面与Method Chaining等同起来。当然链接是一种常用的技术,可以使用流畅的界面,但真正的流畅性远不止于此。
它通常也称为内部DSL,因为语法类似于DSL,但它是在宿主语言中实现的,而不是由解析器处理。
答案 1 :(得分:18)
漏洞抽象是一种抽象,其中潜在现实的细节经常“泄漏”。
All abstractions lie或多或少,但有时抽象与潜在的现实非常不符合,它会带来更多的伤害而不是它的帮助。
抽象中“泄漏”的一个简单示例可能是通常的浮点类型。它似乎代表一般实数,您可以使用它来执行基本计算。但是在某些时候你会遇到一个场景,其中1/3 * 3!= 1或1 + 10 ^ -20 = 1.这就是实际的实现细节泄漏并且抽象中断的时候。
答案 2 :(得分:9)
一个流畅的界面,一个术语埃里克埃文斯创造,它只是方法链的另一个名称。 Martin Fowler在这个问题上写了couple articles,但它大致如下:
m_Window = window::with()
.width(l_Width)
.height(l_Height)
.title("default window")
.left(200)
.top(200)
.create();
Fluent界面通常用于以不支持它们的语言(例如C ++中的命名参数惯例)或域特定语言创建命名参数,以使代码读取更流畅。
我已经看到它们被用于从图像处理库到正则表达式库,3D库的所有内容。其他示例包括树结构,列表或其他数据结构的构造。需要构建复杂对象(参数加载)的所有内容都可以使用Fluent接口使其更具可读性。例如,将前面的示例与CreateWindow函数调用进行比较:
::CreateWindow(
"Window class",
"Window title",
dwStyle, X, Y,
nWidth, nHeight,
hWndPant, hMenu,
hInstance, NULL
);
答案 3 :(得分:5)
这是一个常规的日常界面:
public interface NotFluent
{
void DoA();
void DoB();
void DoC();
}
这里有一个流畅的界面:
public interface Fluent
{
Fluent DoA();
Fluent DoB();
Fluent DoC();
}
最明显的区别是当我们返回一个void时,我们返回一个接口类型的实例。可以理解的是,返回的接口是CURRENT INSTANCE,而不是相同类型的新实例。当然,这是不可执行的,并且在不可变对象(如字符串)的情况下,它是一个不同的实例,但可以被认为是仅更新的同一实例。
以下是其使用示例:
NotFluent foo = new NotFluentImpl();
foo.DoA();
foo.DoB();
foo.DoC();
Fluent bar = new FluentImpl();
bar.DoA().DoB().DoC();
请注意,链接不同的调用时,更容易使用流畅的界面。 IRL,查看Linq扩展方法以及每个调用如何设计为流入另一个。没有一个方法返回void,即使它是有效的结果。
答案 4 :(得分:3)
面向对象的界面流利如果方法执行副作用返回self
,那么这些方法可以链接在一起。
我在1990年第一次遇到流畅的接口时,Modula-3接口警察(我没有这么做)需要所有初始化方法来返回初始化的对象。我相信这种用法早于术语“流畅的界面”的硬币。
答案 5 :(得分:1)
在流畅的界面中,对象的方法将返回对象的引用,以便您可以将方法调用链接在一起。
例如,在NValidate中,我这样做是为了简化参数验证:
public City GetCity(string zipCode)
{
zipCode.Assert("zipCode").IsNotNullOrEmpty().HasLength(5,10).Matches("\\d[5]-\\d[4]");
// Continue processing
}
但是,我不能谈论漏洞抽象。
答案 6 :(得分:1)
谢谢你们。
很棒的描述。
我想到了流畅的界面,它们是为了便于阅读。我总是可以阅读一系列方法,以及如何与上一个/下一个方法相关。
E.g。就像发布验证示例的海报一样(我编写了类似于之前的代码)。
答案 7 :(得分:1)
Neal Ford在他的“生产程序员”一书中解释并提供Fluent Interface示例做得很好。
带有getter / setter的传统对象或'bean':
Car car = new CarImpl();
MarketingDescription des = new MarketingDescriptionImpl();
desc.setType("Box");
desc.setSubtype("Insulated");
desc.setAttribute("length", "50.5");
desc.setAttribute("ladder", "yes");
desc.setAttribute("lining type", "cork");
car.setDescription(desc);
通过流畅的界面满足相同的需求:
Car car = Car.describedAs()
.box()
.length(50.5)
.type(Type.INSULATED)
.includes(Equipment.LADDER)
.lining(Lining.CORK);