得墨忒耳法则 - 务实的程序员

时间:2013-02-05 23:37:01

标签: law-of-demeter

我在考虑“实用程序员”的练习时遇到了一些问题。

它说:

1

public void showBalance(BankAccount acct) {
Money amt = acct. getBalance() ;
printToScreen(amt .printFormat()) ;
}
  

变量acct作为参数传入,因此允许getBalance调用。调用   但是,amt.printFormat()不是。我们不“拥有”amt并且没有传递给我们。

但我们拥有对吗?它在方法和LOD中声明:当您的方法创建本地对象时,该方法可以调用本地对象上的方法。

这个例子打破了LOD吗?我看待它的方式,不是吗?

2

public class Colada {
private Blender myBlender;
private Vector myStuff;

public Colada() {
myBlender = new Blender();
myStuff = new Vector() ;
}

private void doSomething() {
myBlender.addlngredients(myStuff.elements());
}
}
  

由于Colada创建并拥有myBlender和myStuff,因此调用addIngredients和   允许元素。

现在我不明白为什么允许一些东西调用myBlender和myStuff,因为它没有创建它。

3

void processTransaction(BankAccount acct, int) {
Person *who;
Money amt;
amt.setValue(123.45);
acct.setBalance(amt);
who = acct .getOwner() ;
markWorkflow(who->name(), SET_BALANCE);
} 
  

在这种情况下,processTransaction拥有amt,它在堆栈上创建,acct被传入,因此允许setValue和setBalance。但是processTransaction并不拥有谁,所以调用   who-> name()违规。

所以这里它确实声明了谁但不允许对它进行调用。也许我误解了“拥有”的概念。

有人可以澄清一下吗?

由于

1 个答案:

答案 0 :(得分:2)

让我们逐一看看所谓的矛盾。

1

public void showBalance(BankAccount acct) {
    Money amt = acct. getBalance() ;
    printToScreen(amt .printFormat()) ;
}

The variable acct is passed in as a parameter, 
so the getBalance call is allowed. 
Calling amt.printFormat(), however, is not. 
We don't "own" amt and it wasn't passed to us.

此声明完全有效,因为LoD声明虽然acct可以传递给showBalance()showBalance()可以访问getBalance(),但由于直接引用了acct 1}},它可能不会在Money的任何实例上调用任何方法。这是因为没有Money类型的对象传递给showBalance(),它只是通过本地访问器引用它。这并不意味着amt的所有权现在为showBalance()

2

public class Colada {
    private Blender myBlender;
    private Vector myStuff;

    public Colada() {
        myBlender = new Blender();
        myStuff = new Vector() ;
    }

    private void doSomething() {
        myBlender.addlngredients(myStuff.elements());
    }
}

Since Colada creates and owns both myBlender and myStuff, 
the calls to addIngredients and elements are allowed .

现在,这个类构造函数中发生的是BlenderVector对象的声明和实例化。因此,myBlendermyStuff的所有者是班级Colada。 LoD声明对象m的方法o可以访问o的所有直接组件,因此在这种情况下,方法doSomething()可以访问Colada直接使用组件,它可以在BlenderVector上调用myBlendermyStuff的方法。

3

void processTransaction(BankAccount acct, int) {
    Person *who;
    Money amt;
    amt.setValue(123.45);
    acct.setBalance(amt);
    who = acct .getOwner() ;
    markWorkflow(who->name(), SET_BALANCE);
}

In this case, processTransaction owns amt, 
it is created on the stack, acct is passed in, 
so both setValue and setBalance are allowed. 
But processTransaction does not own who, 
so the call who->name() is in violation.

方法processTransaction()收到对象acct中的银行帐户。它初始化类型为Money的对象,设置值,然后在acct上调用setter方法setBalance(),这与LoD一致。由于amt是在processTransaction内创建并初始化的,因此对setValue的{​​{1}}的访问也与LoD一致。现在出现了矛盾。 amt仅仅是指向*who类型对象的指针,只能通过访问器方法Person显示。但是该方法归getOwner所有,因此调用acct上的方法无效,因为它会破坏LoD。

简而言之,LoD声明*who无效,只有a.getB().getC().doSomething()有效。如果我必须用简单的英语写LoD,可以用3个单词指定 - a.getB()

假设Chain Of Command包含Object A实例的层次结构,而Object B包含Object B的实例,则根据LoD,以下内容为true。

  • 对象A无法通过对象B的实例访问和更改对象C.
  • 然而,对象B可以根据它可以从对象A获取的某些条件来访问和更改对象C.

我希望能够解除你的疑虑。