Oop 流畅的接口和漏洞百出的抽象
什么是流畅的界面?我找不到一个很好的定义,但我得到的只是一种我不太熟悉的语言(例如C++)中的长代码示例 还有,什么是泄漏抽象Oop 流畅的接口和漏洞百出的抽象,oop,fluent-interface,leaky-abstraction,Oop,Fluent Interface,Leaky Abstraction,什么是流畅的界面?我找不到一个很好的定义,但我得到的只是一种我不太熟悉的语言(例如C++)中的长代码示例 还有,什么是泄漏抽象 感谢Eric Evans创造的流畅界面,这只是方法链接的另一个名称。马丁·福勒(Martin Fowler)就这一主题写了一篇文章,但大致如下: m_Window = window::with() .width(l_Width) .height(l_Height) .title("default window") .left(200)
感谢Eric Evans创造的流畅界面,这只是方法链接的另一个名称。马丁·福勒(Martin Fowler)就这一主题写了一篇文章,但大致如下:
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
);
这里有一个常规的每日界面:
public interface NotFluent
{
void DoA();
void DoB();
void DoC();
}
public interface Fluent
{
Fluent DoA();
Fluent DoB();
Fluent DoC();
}
Car car = Car.describedAs()
.box()
.length(50.5)
.type(Type.INSULATED)
.includes(Equipment.LADDER)
.lining(Lining.CORK);
这是一个流畅的界面:
public interface NotFluent
{
void DoA();
void DoB();
void DoC();
}
public interface Fluent
{
Fluent DoA();
Fluent DoB();
Fluent DoC();
}
Car car = Car.describedAs()
.box()
.length(50.5)
.type(Type.INSULATED)
.includes(Equipment.LADDER)
.lining(Lining.CORK);
最明显的区别是,当我们返回一个void时,我们返回的是接口类型的实例。可以理解的是,返回的接口是当前实例,而不是相同类型的新实例。当然,这是不可强制执行的,在不可变对象(如字符串)的情况下,它是一个不同的实例,但可以被视为仅更新的同一实例
以下是它们的使用示例:
NotFluent foo = new NotFluentImpl();
foo.DoA();
foo.DoB();
foo.DoC();
Fluent bar = new FluentImpl();
bar.DoA().DoB().DoC();
注意,当链接不同的调用时,fluent接口更容易使用。IRL,检查Linq扩展方法,以及每个调用是如何设计为流入另一个调用的。没有一个方法返回void,即使它是一个有效的结果。在fluent接口中,对象的方法将返回对对象的引用,以便将方法调用链接在一起 例如,在NValidate中,我这样做是为了简化参数验证:
public City GetCity(string zipCode)
{
zipCode.Assert("zipCode").IsNotNullOrEmpty().HasLength(5,10).Matches("\\d[5]-\\d[4]");
// Continue processing
}
不过,我不能说是漏洞百出的抽象。流畅的接口是一种API,它允许您编写读起来或多或少像普通英语的代码。例如:
Find.All.Questions(Where.IsAnswered == true);
方法链接通常作为实现的一部分使用,但它还有更多的功能。引述:
我还注意到一个常见的误解——许多人似乎将流畅的接口等同于方法链接。当然,链接是一种用于流畅界面的常见技术,但真正的流畅远不止于此
它也经常被称为内部接口,因为语法类似于DSL,但它是在宿主语言内部实现的,而不是由解析器处理。如果为副作用而执行的方法返回
self
,则面向对象的接口是流畅的,这样就可以将这些方法链接在一起
我第一次遇到fluent接口是在1990年,当时Modula-3接口警察(我不是编造这个)要求所有初始化方法返回初始化的对象。我相信这种用法早于“流畅的界面”这一术语的出现。泄漏的抽象是一种抽象,在这种抽象中,潜在现实的细节常常“泄漏” 多多少少,但有时抽象与潜在现实的契合度太差,以至于造成的伤害大于帮助 抽象中“泄漏”的一个简单示例可能是常见的浮点类型。它似乎代表一般实数,您可以使用它来执行基本计算。但有时您会遇到这样一种情况,即1/3*3!=1或1+10^-20=1。这就是实际的实现细节泄露,抽象中断的时候。谢谢大家 很好的描述 我对流畅界面的想法是为了可读性。我总是可以阅读一系列方法,以及其中一个方法与上一个/下一个方法的关系 例如,就像张贴验证示例的海报一样(我编写了与之前类似的代码)。在他的《高效程序员》一书中很好地解释并给出了流畅的界面示例 具有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);
通过流畅的界面满足同样的需求:
public interface NotFluent
{
void DoA();
void DoB();
void DoC();
}
public interface Fluent
{
Fluent DoA();
Fluent DoB();
Fluent DoC();
}
Car car = Car.describedAs()
.box()
.length(50.5)
.type(Type.INSULATED)
.includes(Equipment.LADDER)
.lining(Lining.CORK);
我已经有一段时间没有做任何与web相关的开发了,但从jQuery文档来看,似乎是这样。这是方法链接,而不是流畅的接口。参见上面Rasmus回答的引语“当然,链接是流畅界面使用的一种常见技术,但真正的流畅远不止于此……”这应该作为两个独立的问题发布。而且。。fluent接口的优缺点是什么?这个例子不是简单的方法链接吗?福勒注意到。上面的代码有什么特性使它成为一个流畅的界面,而不仅仅是方法链接?@Pacerier如果你有兴趣分割这根头发(而引用的内容根本没有像作者所想象的那样有区别),那么与其对每个答案都加注释,为什么不自己回答呢?或者,如果你想了解更多关于如何分割头发的知识,可以问一个新问题,集中讨论两种头发之间的区别。就我个人而言,我看不到太多。绝对不足以做出有价值的区分。我看到它们密不可分地联系在一起。只是有时候模式会出现,有时候不会。我想我对美学不感兴趣。关于“为什么不自己回答它”,我没有答案,因此产生了问题。这不是“吹毛求疵”,很明显FluentInterface不等于方法链接。@Pacerier哦,这没有任何意义。你声称很明显他们是不同的,但你自己却没有答案?我相信你在开玩笑。您好,先生。我不明白为什么rep的数量与t相关