「デメテルの法則」とタグ付けされた問題はほぼすべて読みました。私の特定の質問は、これらの他の質問のいずれにも答えられていませんが、非常に似ています. 主に私の質問は、構成のレイヤーを持つオブジェクトがある場合ですが、さまざまなオブジェクトからプロパティ値を取得する必要がある場合です。これをどのように達成し、なぜあるアプローチを別のアプローチよりも優先するのでしょうか?
次のように、他のオブジェクトで構成された非常に標準的なオブジェクトがあるとします。
public class Customer {
private String name;
private ContactInfo primaryAddress;
private ContactInfo workAddress;
private Interests hobbies;
//Etc...
public getPrimaryAddress() { return primaryAddress; }
public getWorkAddress() { return workAddress; }
public getHobbies() { return hobbies; }
//Etc...
}
private ContactInfo {
private String phoneNumber;
private String emailAddress;
//Etc...
public getPhoneNumber() { return phoneNumber; }
public getEmailAddress() { return emailAddress; }
//Etc...
}
private Interests {
private List listOfInterests;
}
以下は両方ともデメテルの法則に違反します。
System.out.println("Phone: " + customer.getPrimaryAddress().getPhoneNumber());
System.out.println("Hobbies: " + customer.getHobbies().getListOfInterests().toString());
これはまた、デメテルの法則に違反すると思います (明確化?):
ContactInfo customerPrimaryAddress = customer.getPrimaryAddress();
System.out.println("Phone: " + customerPrimaryAddress.getPhoneNumber());
したがって、おそらく、「getPrimaryPhoneNumber()」メソッドを Customer に追加します。
public getPrimaryPhoneNumber() {
return primaryAddress.getPhoneNumber();
}
そして、次のように呼び出します: System.out.println("Phone: " + customer.getPrimaryPhoneNumber());
しかし、これを時間をかけて行うと、実際には多くの問題が発生し、デメテルの法則の意図に反するように思えます。これにより、Customer クラスは、独自の内部クラスについてあまりにも多くの知識を持つ getter と setter の巨大なバッグになります。たとえば、Customer オブジェクトは、ある日、さまざまなアドレス (「プライマリ」アドレスと「勤務先」アドレスだけでなく) を持つ可能性があるようです。おそらく、Customer クラスでさえ、特定の名前の ContactInfo オブジェクトではなく、単に ContactInfo オブジェクトの List (またはその他のコレクション) を持つことになります。その場合、どのようにデメテルの法則に従い続けますか? 抽象化の目的を無効にしているように見えます。たとえば、Customer が ContactInfo アイテムの List を持っているような場合、これは妥当と思われます。
Customer.getSomeParticularAddress(addressType).getPhoneNumber();
一部の人々が携帯電話と固定電話を持っていることを考えると、これはさらにおかしなことになり、ContactInfo は電話番号のコレクションを持たなければならないように思えます。
Customer.getSomeParticularAddress(addressType).getSomePhoneNumber(phoneType).getPhoneNumber();
その場合、オブジェクト内のオブジェクト内のオブジェクトを参照するだけでなく、有効な addressType と phoneType が何であるかを知る必要もあります。これには間違いなく問題がありますが、回避する方法がわかりません。特に、これを呼び出しているクラスが何であれ、問題の顧客の「プライマリ」アドレスの「携帯」電話番号を取得したいことをおそらく知っているでしょう。
デメテルの法則に準拠するためにこれをどのようにリファクタリングできますか?また、それがなぜ良いのでしょうか?