关于wikipedia article的Law of Demeter说:
法律可以简单地称为“只使用一个点”。
但simple example的fluent interface可能如下所示:
static void Main(string[] args)
{
new ZRLabs.Yael.Pipeline("cat.jpg")
.Rotate(90)
.Watermark("Monkey")
.RoundCorners(100, Color.Bisque)
.Save("test.png");
}
这是一起的吗?
答案 0 :(得分:75)
嗯,法律的简短定义缩短了太多。真正的“法律”(实际上是关于良好API设计的建议)基本上说:只访问您自己创建的对象,或者作为参数传递给您。不要通过其他对象间接访问对象。流畅接口的方法通常返回对象本身,因此如果再次使用对象,它们不会违反法律。其他方法为您创建对象,因此也没有违规。
另请注意,“法律”仅是“经典”API的最佳实践建议。 Fluent接口是一种完全不同的API设计方法,无法使用Demeter法进行评估。
答案 1 :(得分:24)
不一定。 “只使用一个点”是对得墨忒耳法的不准确的总结。
当每个点代表不同对象的结果时,Demeter法则不鼓励使用多个点,例如:
但是,至少在我看来,如果每个点的返回对象仍然与原始调用者的类型相同,则不会违反Demeter法则:
var List<SomeObj> list = new List<SomeObj>();
//initialize data here
return list.FindAll( i => i == someValue ).Sort( i1, i2 => i2 > i1).ToArray();
在上面的示例中,FindAll()和Sort()都返回与原始列表相同类型的对象。德米特定律没有被违反:该名单只与其直接的朋友交谈。
如果说并非所有流畅的界面都违反了得墨忒耳法则,只要它们返回与其来电者相同的类型。
答案 2 :(得分:8)
是的,虽然你必须对这种情况采取一些实用主义。我总是把德米特定律作为指导而不是规则。
当然,您可能希望避免以下情况:
CurrentCustomer.Orders[0].Manufacturer.Address.Email(text);
或许替换为:
CurrentCustomer.Orders[0].EmailManufacturer(text);
由于我们中的更多人使用ORM,它通常将整个域作为对象图表,因此可能需要为特定对象定义可接受的“范围”。也许我们应该采用demeter定律来建议你不要将整个图形映射为可达。
答案 3 :(得分:7)
Demeter定律的精神在于,给定一个对象引用或类,您应该避免访问多于一个子属性或方法的类的属性,因为这将紧密地耦合这两个类,这可能是无意的并且可能导致可维护性问题。
Fluent接口是法律可接受的例外,因为它们意味着至少有点紧密耦合,因为所有属性和方法都是由一起组成的迷你语言的术语形成功能性句子。
答案 4 :(得分:6)
1)它完全没有违反它。
代码相当于
var a = new ZRLabs.Yael.Pipeline("cat.jpg");
a = a.Rotate(90);
a = a.Watermark("Monkey");
a = a.RoundCorners(100, Color.Bisque);
a = a.Save("test.png");
2)正如Good Ol'Phil Haack所说:The Law of Demeter Is Not A Dot Counting Exercise
答案 5 :(得分:1)
您的示例没有问题。毕竟,你是旋转,水印等...总是相同的图像。我相信你一直在与Pipeline对象交谈,所以只要你的代码只依赖于Pipeline的类,你就不会违反LoD。
答案 6 :(得分:1)
从本质上讲,对象不应公开其内部(数据),而应公开用于内部操作的函数。
考虑到这一点,Fluent API要求对象使用其数据处理某些事情,而不是询问其数据。
这不违反任何《得墨meter耳定律》。