Чтобы на наглядном примере увидеть, как с применением внутренних классов достигается простота создания и использования библиотек, мы рассмотрим систему, ориентированную на обработку событий по их «готовности». Хотя в практическом смысле под «готовностью» может пониматься все, что угодно, в нашем случае она будет определяться по показаниям счетчика времени. Далее приводится общее описание управляющей системы, никак не зависящей от того, чем именно она управляет. Нужная информация предоставляется посредством наследования, при реализации метода action().
Начнем с определения интерфейса, описывающего любое событие системы. Вместо интерфейса здесь используется абстрактный класс, поскольку по умолчанию управление координируется по времени, а следовательно, присутствует частичная реализация:
//: innerclasses/control 1er/Event.java
// Общие для всякого управляющего события методы.
package innerclasses/controller;
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime = delayTime; startO;
}
public void startO { // Позволяет перезапуск eventTime = System nanoTimeO + delayTime;
}
public boolean readyО {
return System.nanoTimeO >= eventTime;
}
public abstract void actionO; } ///:-
Конструктор просто запоминает время (от момента создания объекта), через которое должно выполняться событие Event, и после этого вызывает метод start(), который прибавляет к текущему времени интервал задержки, чтобы вычислить время возникновения события. Метод start() отделен от конструктора, благодаря чему становится возможным «перезапуск» события после того, как его время уже истекло; таким образом, объект Event можно использовать многократно. Скажем, если вам понадобится повторяющееся событие, достаточно добавить вызов start() в метод action().
Метод ready() сообщает, что пора действовать — вызывать метод action(). Конечно, метод ready() может быть переопределен любым производным классом, если событие Event активизируется не по времени, а по иному условию.
Следующий файл описывает саму систему управления, которая распоряжается событиями и инициирует их. Объекты Event содержатся в контейнере List
//: innerclasses/control 1er/Control1er.java // Обобщенная система управления package innerclasses.controller; import java.util.*;
public class Controller {
// Класс из пакета java.util для хранения событий Event: private List
while(eventList.size() > 0) {
for(Event e : new ArrayList
System.out.println(e): e.actionO; eventList.remove(e):
}
}
} ///:-
Метод run() в цикле перебирает копию eventList в поисках событий Event, готовых для выполнения. Для каждого найденного элемента он выводит информацию об объекте методом toString(), вызывает метод action(), а после этого удаляет событие из списка.
Заметьте, что в этой архитектуре совершенно неважно,
На этом этапе в дело вступают внутренние классы. Они позволяют добиться двух целей:
1. Вся реализация системы управления создается в одном классе, с полной инкапсуляцией всей специфики данной реализации. Внутренние классы используются для представления различных разновидностей action(), необходимых для решения задачи.
2. Внутренние классы помогают избежать громоздкой, неудобной реализации, так как у них есть доступ к внешнему классу. Без этой возможности программный код очень быстро станет настолько неприятным, что вам захочется поискать другие альтернативы.