内部类也通常运行在各种控制框架中。要运用某个控制框架,一般是继承一个或者多个类,并且覆盖某些方法。在覆盖后的方法中,编写特定的代码来解决特定的问题。比如在事件机制中相应事件的需求。
下面就是一个简单的事件驱动控制框架,它的工作就是在 就绪 时执行事件, 下面的例子是基于事件触发的事件,对于要控制什么,框架并不包含任何具体的信息。那些信息是在实现算法action()时,通过继承来提供的。
首先,开始描述一个基于事件控制的事件。
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime){
this.delayTime = delayTime;
start();
}
public void start(){
eventTime = System.nanoTime() + delayTime;
}
public boolean ready(){
return System.nanoTime() >= eventTime;
}
public abstract void action();
}
当希望运行Event中的start()时,构造器就会捕获时间,此时间就是获取当前的时间然后加上一个延迟的时间用来生产触发事件的时间。
ready()则是可以何时运行action的方法,也可以在导出类中覆盖ready()方法,这样就可以使得Event基于其它因素触发。
下面则是包含了一个用来管理和触发事件的实际的控制框架,Event对象被保存在一个Event队列中。
public class Controller {
private List<Event> eventList = new ArrayList<Event>();
public void addEvent(Event c){
eventList.add(c);
}
public void run(){
while(eventList.size() > 0){
for(Event e : new ArrayList<Event>(eventList)){
if(e.ready()){
System.out.println(e);
e.action();
eventList.remove(e);
}
}
}
}
}
run()方法循环遍历eventList,寻找就绪的(ready())对象,对于每一个将要运行的Event事件,调用其action()方法,然后从队列中移除此队列。
目前的设计中我们并不知道Event具体做了什么,这正是此设计的关键所在,“是变化的事物和不变的事物相互分离”,这正是内部类所做的事情,内部类允许控制框架的完整实现由单个的类创建,从而使得实现的细节被封装起来。内部类用来表示解决问题所必须的各种不同的action()。如下面的例子所示,假设一个智能家居的控制框架可以实现自动开关灯,自动播放音乐等。使用内部类,可以在单一的类里面产生对同一个基类Event的多种导出版本。对于智能家居系统的每一个行为,都要继承一个新的Event类。
public class HouseControls extends Controller{
private boolean light = false;
public class LightOn extends Event{
public LightOn(long delayTime) { super(delayTime);}
public void action(){light = true;}
public String toString(){return "light is on";}
}
public class LightOff extends Event{
public LightOff(long delayTime) { super(delayTime);}
public void action(){light = false;}
public String toString(){return "light is off";}
}
public class Music extends Event{
public Music(long delayTime){ super(delayTime); }
public void action(){
addEvent(new Music(delayTime));
}
public String toString(){ return "Bell Bing!";}
}
public class Restart extends Event{
private Event[] eventList;
public Restart(long delayTime,Event[] eventList){
super(delayTime);
this.eventList = eventList;
for(Event e : eventList){
addEvent(e);
}
}
public void action(){
for(Event e : eventList){
e.start();
addEvent(e);
}
start();
addEvent(this);
}
public String toString(){return "Restarting System";}
}
public static class Terminate extends Event{
public Terminate(long delayTime) {super(delayTime);}
public void action() {System.exit(0);}
public String toString(){return "Terminating";}
}
}
一个Event对象组成的数组被递交给Restart,由于Restart也是一个Event对象,所以同样可以将一个Restart对象添加到Restart.action(),以便系统能过有规律的重启自己。
public class HouseController {
public static void main(String args[]){
HouseControls hc = new HouseControls();
hc.addEvent(hc.new Music(800));
Event[] eventList = {
hc.new LightOn(0),
hc.new Music(500),
hc.new LightOff(1000)
};
hc.addEvent(hc.new Restart(2000, eventList));
if(args.length == 1){
hc.addEvent(new HouseControls.Terminate(new Integer(args[0])));
}
hc.run();
}
}
这个类的作用是初始化系统,添加了所有的事件。Restart事件反复运行,而且每次都会将eventlist加载到HouseControls对象中。
上面就是内部类应用在特殊的控制框架中,Java的Swing库就是一个控制框架,它优雅地解决了Java的GUI问题并使用了大量的内部类。