Я прочитал почти все вопросы, отмеченные Законом о Деметере. Мой конкретный вопрос не отвечает ни на один из этих вопросов, хотя он очень похож. В основном, мой вопрос заключается в том, когда у вас есть объект со слоями композиции, но нужно извлекать значения свойств из разных объектов, как вы это достигаете и зачем использовать один подход над другим?
Скажем, у вас есть довольно стандартный объект, состоящий из других объектов, например:
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()" к клиенту:
public getPrimaryPhoneNumber() {
return primaryAddress.getPhoneNumber();
}
А потом просто позвоните: System.out.println( "Телефон:" + customer.getPrimaryPhoneNumber());
Но делать это со временем кажется, что это фактически обеспечит много проблем и будет работать против намерения Закона Деметры. Это делает класс Клиента огромным пакетом геттеров и сеттеров, который имеет слишком много знаний о своих внутренних классах. Например, представляется возможным, что объект Customer однажды будет иметь разные адреса (а не только "первичный" и "рабочий" адрес). Возможно, даже класс Customer просто будет иметь список (или другую коллекцию) объектов ContactInfo, а не конкретные объекты ContactInfo. Как вы продолжаете следовать Закону Деметры в этом случае? Казалось бы, это победит цель абстракции. Например, это кажется разумным в таком случае, когда у Клиента есть список элементов ContactInfo:
Customer.getSomeParticularAddress(addressType).getPhoneNumber();
Кажется, что он может стать еще более сумасшедшим, когда вы думаете о некоторых людей, имеющих мобильный телефон и стационарный телефон, а затем ContactInfo должен иметь набор телефонных номеров.
Customer.getSomeParticularAddress(addressType).getSomePhoneNumber(phoneType).getPhoneNumber();
В этом случае мы не только ссылаемся на объекты внутри объектов внутри объектов, но также должны знать, каков действительный тип addressType и phoneType. Я определенно вижу проблему с этим, но я не уверен, как этого избежать. Особенно, когда какой-либо класс вызывает это, вероятно, знает, что они хотят вытащить "мобильный" номер телефона для "первичного" адреса данного клиента.
Как это можно было бы реорганизовать, чтобы соответствовать Закону Деметры и почему это было бы хорошо?