Брюс Эккель - Философия Java3
- Название:Философия Java3
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Брюс Эккель - Философия Java3 краткое содержание
Философия Java3 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
//. 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;
} ///:-
В общем случае объект с неопределенным состоянием является синглетным, поэтому он создается как экземпляр static final. Это возможно благодаря тому, что объект Person неизменяем — значения задаются в конструкторе, а затем читаются, но не могут изменяться (поскольку поля String по своей природе неизменяемы). Если вы захотите изменить NullPerson, его придется заменить новым объектом Person. Обратите внимание: для обнаружения обобщенной поддержки Null или более конкретного типа NullPerson можно использовать instanceof, но при синглетной архитектуре можно воспользоваться просто equals() или даже == для сравнения с Person.NULL.
Представьте, что вы собираетесь открыть новое предприятие, но, пока вакансии еще не заполнены, в каждой должности 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 {
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) {
Staff staff = new Staff("President", "СТО",
"Marketing Manager", "Product Manager". "Project Lead", "Software Engineer", "Software Engineer", "Software Engineer", "Software Engineer", "Test Engineer", "Technical Writer"); sta ff.fi11Pos i t i on("Pres i dent".
new PersonCMe", "Last". "The Top, Lonely At")); staff.fi11Position("Project Lead".
new PersonC"Janet". "Planner". "The Burbs")); if(staff.positionAvailableC"Software Engineer")) staff.fi11Position("Software Engi neer". new PersonO'Bob". "Coder". "Bright Light City"));
System.out.printin(staff).
}
} /* Output:
[Position: President Person: Me Last The Top. Lonely At. Position. СТО NullPerson. Position: Marketing Manager NullPerson. Position: Product Manager NullPerson. Position. Project Lead Person: Janet Planner The Burbs. Position: Software Engineer Person: Bob Coder Bright Light City. Position: Software Engineer NullPerson. Position: Software Engineer NullPerson. Position- Software Engineer NullPerson. Position. Test Engineer NullPerson. Position: Technical Writer NullPerson] *///.-
Обратите внимание: в некоторых местах нам по-прежнему приходится проверять объекты на определенное состояние, что принципиально не отличается от проверки null, но в других местах, скажем, при преобразованиях toStringO), лишние проверки не нужны; мы просто считаем, что ссылка на объект действительна.
Если вместо конкретных классов используются интерфейсы, для автоматического создания объектов с неопределенным состоянием можно воспользоваться динамическим посредником. Допустим, имеется интерфейс Robot, определяющий имя и модель робота, а также список List, определяющий, какие операции выполняет робот. Операция состоит из описания и команды:
//: typeinfo/Operation java
public interface Operation { String description): void commandO; } ///.-
Чтобы воспользоваться услугами робота, следует вызвать метод operations():
//: typeinfo/Robot.java import java.util *; import net.mindview util.*:
public interface Robot { String nameO, String model О; List operationsO: class Test {
public static void test(Robot r) { if(r instanceof Null)
System.out.pri ntin("[Nul1 Robot]"). System.out.println("Ha3BaHMe- " + r.nameO); System, out. pri nti n( "Модель " + r.model О). for(Operation operation : r.operationsO) {
System, out. pri nti n(operati on description)): operation.commandO;
}
}
}
} ///.-
При этом используется вложенный класс, выполняющий проверку. Теперь мы можем создать робота для уборки снега:
// typeinfo/SnowRemovalRobot java import java util.*.
public class SnowRemovalRobot implements Robot { private String name.
public SnowRemovalRobot(String name) {this name = name,} public String nameО { return name; } public String model О { return "SnowBot Series 11". } public List operations О { return Arrays.asListC
new OperationO {
public String description) {
return name + " может убирать снег",
}
public void commando {
System out.println(name + " убирает снег"),
}
}.
new OperationO {
public String descriptionO {
return name + " может колоть лед".
}
public void commando {
System out println(name + " колет лед");
}
ь
new OperationO {
public String descriptionO {
return name + " может чистить крышу";
}
public void commando {
System out.println(name + " чистит крышу"),
}
}
);
}
public static void main(String[] args) {
Robot Test.test(new SnowRemovalRobot("SIusher"));
}
} /* Output: Название: Slusher Модель: SnowBot Series 11 Slusher может убирать снег Slusher убирает снег Slusher может колоть лед-Si usher колет лед Slusher может чистить крышу Slusher чистит крышу *///:-
Предполагается, что существуют разные типы роботов, и для каждого типа Robot объект с неопределенным состоянием должен делать что-то особенное — в нашем примере выдавать информацию о конкетном типе Robot, представленном объектом. Эта информация перехватывается динамическим посредником:
//: typeinfo/NullRobot.java
// Использование динамического посредника для создания
// объекта с неопределенным состоянием import java.lang.reflect *, import java util *, import net.mindview util.*;
class NullRobotProxyHandler implements InvocationHandler { private String null Name; private Robot proxied = new NRobotO. NullRobotProxyHandler(CIass
Интервал:
Закладка: