得墨忒耳定律 - 数据对象

Tom*_*m B 10 theory oop law-of-demeter

我试图按照法律的德米特(见http://en.wikipedia.org/wiki/Law_of_Demeter,http://misko.hevery.com/code-reviewers-guide/flaw-digging-into-collaborators/)因为我可以看到它的好处,但是当涉及到域对象时,我变得有点卡住了.

域对象自然有链,有时需要显示有关整个链的信息.

例如,一个购物篮:

每个订单包含用户,交货信息和项目清单每个订单项目包含产品和数量每个产品都有名称和价格.每个用户都包含一个名称和地址

显示订单信息的代码必须使用有关订单,用户和产品的所有信息.

当然,通过订单对象获取此信息更好,更可重用,例如"order.user.address.city",而不是上面列出的所有对象的某些代码,然后将它们分别传递给代码?

欢迎提出任何意见/建议/提示!

das*_*ght 10

使用链式引用的一个问题order.user.address.city是,高阶依赖性被"烘焙"到类外部的代码结构中.

理想情况下,在重构类时,"强制更改"应限于被重构的类的方法.当您在客户端代码中有多个链式引用时,重构会驱使您在代码的其他位置进行更改.

考虑这样一个例子:假设你想更换UserOrderPlacingParty,抽象封装的用户,公司和电子剂,可以下订单.这种重构立即出现了多个问题:

  • User属性将被称为其他属性,它将具有不同的类型
  • 新的属性可以不具有address具有city当订单由电子剂放置在箱子
  • 人类User与订单相关联(假设你的系统需要一个法律上的原因),可以间接地涉及到订单, -例如,通过被指定去到人的定义OrderPlacingParty.

这些问题的解决方案是将订单表示逻辑直接传递给它所需的一切,而不是让它"理解"传入的对象的结构.这样你就能够对被重构的代码进行本地化更改,不将更改传播到其他可能稳定的代码.

interface OrderPresenter {
    void present(Order order, User user, Address address);
}
interface Address {
    ...
}
class PhysicalAddress implements Address {
    public String getStreetNumber();
    public String getCity();
    public String getState();
    public String getCountry();
}
class ElectronicAddress implements Address {
    public URL getUrl();
}
interface OrderPlacingParty {
    Address getAddress();
}
interface Order {
    OrderPlacingParty getParty();
}
class User implements OrderPlacingParty {
}
class Company implements OrderPlacingParty {
    public User getResponsibleUser();
}
class ElectronicAgent implements OrderPlacingParty {
    public User getResponsibleUser();
}
Run Code Online (Sandbox Code Playgroud)