Философия Java3
Шрифт:
new Class[]{ SomeMethods.class }. new MethodSelector(new Implementation))); proxy.boringlO; proxy.boring2; proxy.i nteresti ng("bonobo"); proxy.boring3;
}
} /* Output:
boringl
boring2
Посредник обнаружил интересный метод interesting bonobo boring3 *///:-
В данном случае мы просто проверяем имена методов, но с таким же успехом можно анализировать другие аспекты сигнатуры и даже значения аргументов.
Вряд ли вам придется каждый день пользоваться динамическими посредниками, но они хорошо подходят для решения многих разновидностей задач.
Объекты с неопределенным состоянием
Если
Было бы интересно представить себе язык программирования, автоматически создающий объекты с неопределенным состоянием, но на практике они применяются не так уж часто — иногда проверки null оказывается достаточно, иногда можно уверенно считать, что значение null вам не попадется, а иногда даже обработка аномальных ситуаций через NullPointerException является допустимой. Наибольшую пользу объекты с неопределенным состоянием приносят «вблизи от данных», представляя сущности в пространстве задачи. Простой пример: во многих системах имеется класс Person, а в коде возникают ситуации, когда объект не представляет конкретную личность (или, по крайней мере, информация о ней недоступна); при традиционном подходе вам следовало бы проверить ссылку null. Также можно воспользоваться объектом с неопределенным состоянием, но, даже несмотря на то, что такой объект будет отвечать на все сообщения, на которые отвечает «настоящий» объект, все равно потребуется способ проверки его на «определенность». Проще всего определить для этого специальный интерфейс:
//. net/mindview/uti1/Null java package net.mindview util; public interface Null {} ///•-
Это позволяет instanceof обнаруживать объекты с неопределенным состоянием и, что еще важнее, не требует включения метода isNull во все классы (в конце концов, это фактически будет другим способом выполнения RTTI — так почему бы сразу не воспользоваться встроенными средствами?):
// typeinfo/Person java
// Класс с неопределенным состоянием объекта
import net mindview util.*;
class Person {
public final String first; public final String last; public final String address; // И т д.
public Person(String first. String last, String address){ this.first = first;
1 Идея принадлежит Бобби Вульфу (Bobby Woolf) и Брюсу Андерсону (Bruce Anderson).
this.last = last; this.address = address;
}
public String toStringO {
return "Person: " + first + " " + last + " " + address;
}
public static class NullPerson extends Person implements Null {
private NullPerson^) { super("None". "None". "None"); } public String toStringO { return "NullPerson"; }
}
public static final Person NULL = new NullPersonO;
} ///:-
В
Представьте, что вы собираетесь открыть новое предприятие, но, пока вакансии еще не заполнены, в каждой должности Position можно временно хранить «заполнитель» — объект Person с неопределенным состоянием:
//• typeinfo/Position.java
class Position {
private String title; private Person person;
public Position(String jobTitle. Person employee) { title = jobTitle; person = employee; if(person == null)
person = Person.NULL;
}
public Position(String jobTitle) { title = jobTitle; person = Person.NULL;
}
public String getTitleO { return title; } public void setTitle(String newTitle) { title = newTitle;
}
public Person getPersonО { return person; } public void setPerson(Person newPerson) { person = newPerson. if(person == null)
person = Person.NULL;
}
public String toStringO {
return "Position: " + title + " " + person; продолжение &
}
} ///:-
Превращать Position в объект с неопределенным состоянием не обязательно, потому что существование Person.NULL подразумевает неопределенность Position (возможно, позднее выяснится, что явная поддержка неопределенного состояния для Position нужна, и вы добавите ее, но в соответствии с одним из канонов экстремального программирования в начальный проект следует включить «простейшее решение, которое будет работать», и включать новые функции лишь по мере возникновения реальной необходимости).
Теперь класс Staff может проверять объекты с неопределенным состоянием при заполнении вакансий:
//: typeinfo/Staff.java
import java util.*;
public class Staff extends ArrayList<Position> {
public void addCString title, Person person) { add(new PositionCtitle, person)),
}
public void add(String.. titles) { for(String title : titles)
add(new PositionCtitle));
}
public StaffCString. titles) { add(titles); }
public boolean positionAvailable(String title) { for(Position position : this)
if(position.getTitleO.equals(title) &&
position.getPersonO == Person.NULL) return true;
return false,
}
public void fillPosition(String title, Person hire) { for(Position position ; this)
if(position.getTitleO.equals(title) &&
position.getPersonO == Person.NULL) { position.setPerson(hire); return;
}
throw new RuntimeException(
"Position " + title + " not available");
}
public static void main(String[] args) {