2013-02-05 41 views
1

我在考慮「實用程序員」中的練習時有一些問題。德米特法 - 實用程序員

它說:

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()); 
} 
} 

由於飄香創建並擁有兩個myBlender和的MyStuff,以addIngredients呼叫和 元件是允許的。

現在我不明白爲什麼doSomething允許調用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()違規。

因此,它確實聲明瞭誰,但不允許調用它。也許我誤解了「擁有」的概念。

有人可以澄清這一點嗎?

謝謝

回答

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. 

這種說法是完全有效的,因爲毀滅之王指出,雖然acct可以傳遞給showBalance()showBalance()可以訪問getBalance()由於具有直接參考acct,它可能不會調用任何方法在任何情況下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 . 

,是什麼在這個類的構造函數的情況是申報和Blender的實例和Vector對象。因此,myBlendermyStuff的所有者是類別Colada。毀滅之王指出對象o的方法m可以訪問所有的直流分量的o,所以在這種情況下,方法doSomething()直接訪問Colada的組成部分,它可以致電myBlendermyStuffBlenderVector方法。

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初始化,獲得的amtsetValue也符合毀滅之王線。現在出現矛盾。 *who僅僅是指向Person類型的對象的指針,該對象只能通過訪問器方法getOwner纔可見。但該方法歸acct所有,因此在*who上調用方法是無效的,因爲它會中斷LoD。

總之,LoD指出a.getB().getC().doSomething()無效,只有a.getB()有效。如果我必須用普通英文寫LoD,可以用3個字 - Chain Of Command來指定。

假設其中Object A包含Object B實例的層次結構,並Object B包含Object C一個實例,根據的LoD以下成立。

  • 對象A不能訪問,並通過對象B的一個實例改變對象C
  • 對象B可以,但是,基於某些準則,它可以從對象A取的訪問和改變對象C

我希望能清除你的疑惑。

+0

謝謝,我現在開始瞭解它。在第一個例子中,它實際上是b = a.getBalance; b.printC;所以相當於a.getB.printC。理解LoD也很有趣:[Demeter](http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf) – Absolem

相關問題