|
Smart Ticket 的优势
较老的移动商务平台,比如基于WAP/WML的微型浏览器将所有的信息处理都放置在服务器端。J2ME的一个重要优势是它支持运行在客户机上智能客户端程序。Smart Ticket充分体现了智能客户端应用程序范例的优势:
◆丰富的UI:在MIDP 2.0中利用了LCDUI增强的特性,Smart Ticke客户端提供一个极好的用户界面。例如,它允许用户通过交互式座位视图选择座位。当你浏览影院放映时间表并选择日期时,MIDlet就会动态地在当前屏幕中添加放映时间。
◆缓存首选项:用户首选项被完全缓存以支持完全个性化 -- 这是移动商务的核心价值所在。例如,您无需输入邮政编码、信用卡号,或者甚至每次输入使用Smart Ticket的个人登录信息,这大大减少了击键工作量。
◆脱机功能:有限且不稳定的移动网络覆盖已经阻碍了基于微型浏览器的“持续连接”应用程序的发展。J2ME 智能客户端程序遵循“间断连接”范例,使用存储在客户设备上的数据并根据需要同步驻留在服务器端的数据-Smart Ticket支持脱机浏览下载的放映时间表和对电影进行评级就是一个很好的例子。
◆高性能缓存:下载的放映时间表也适合于性能缓存,哪怕是在客户设备处于连接状态时。这样减少了对多次往返过程的需求,因为这种过程是非常缓慢的。
◆智能同步:智能客户端程序使用的程序缓存需要定期的从服务端更新。电影放映时间表可以直接由用户下载,而评级可以通过驻留在客户端和服务端的智能代理来进行同步。
怎样实现这些特性?
重要的体系结构模式
总体 MVC 模式
Smart Ticket 应用程序的总体体系结构遵循模式-视图-控制器(Model-View-Controller)模式。这个应用程序被分为多个逻辑层,因此开发人员在修改一部分时不会影响其他部分。 Smart Ticket符合MVC模型,如下所示:
◆视图:每个视图类显示一个交互式UI(用户界面)屏幕,等待用户输入。当用户通过按键或从列表中选择一个条目时将产生一个UI事件,视图类的事件处理程序捕获这个事件,并将控制传递给控制器类。在com.sun.j2me.blueprints.smartticket.client.midp.ui包中的大多数类都是视图类。
<%@ control language="c#" autoeventwireup="true" codefile="webusercontrol2.ascx.cs" inherits="webusercontrol2" %> public class ChooseMovieUI extends Form implements
CommandListener, ItemStateListener,
ItemCommandListener {
private UIController uiController;
// ...
public void commandAction(Command command, Displayable
displayable) { uiController.commandAction(command,
displayable);
}
public void commandAction(Command command, Item item) {
if (command == selectSeatsCommand) {
if (numOfTickets.getString().length() == 0
|| Integer.parseInt(numOfTickets.getString())
< 1) {
uiController.showErrorAlert(
uiController.getString(
UIConstants.NUM_OF_TICKET_ERR));
} else {
uiController.selectSeatsSelected(
movieSchedules[movieList.getSelectedIndex()],
getShowTimes());
}
}
}
} |
◆控制器:控制器类感知用户和程序之间的所有可能的交互。在Smart Ticket中,UIController类有用于每个可能动作的方法,例如,purchaseRequested()。动作方法经常启动两个新的线程,一个用于执行后台的动作,另一个用于向用户显示进度条。动作线程通过EventDispatcher类来表示,它的run()方法包括一条很长的switch语句,此语句在模型层调用合适的方法完成事件请求。当这些方法的最后一次调用返回时,控制器初始化下一个UI画面并显示出来。
package com.sun.j2me.blueprints.smartticket.client.midp.ui;
public class UIController {
// references to all UI classes
// ...
public UIController(MIDlet midlet, ModelFacade model) {
this.display = Display.getDisplay(midlet);
this.model = model;
}
// ...
public void selectSeatsSelected(TheaterSchedule.MovieSchedule
movieSchedule, int[] showTime) {
selectedShowTime = showTime;
selectedMovie = movieSchedule.getMovie();
selectedMovieSchedule = movieSchedule;
runWithProgress(
new EventDispatcher(EventIds.EVENT_ID_SELECTSEATSSELECTED,
mainMenuUI),
getString(UIConstants.PROCESSING), false);
}
class EventDispatcher extends Thread {
private int taskId;
private Displayable fallbackUI;
EventDispatcher(int taskId, Displayable fallbackUI) {
this.taskId = taskId;
this.fallbackUI = fallbackUI;
return;
}
public void run() {
try {
switch (taskId) {
// cases ...
case EventIds.EVENT_ID_SELECTSEATSSELECTED: {
SeatingPlan seatingPlan =
selectedMovieSchedule.getSeatingPlan(selectedShowTime);
String movieName = selectedMovie.getTitle();
seatingPlanUI.init(selectedTheater.getName(), movieName,
seatingPlan, selectedShowTime);
display.setCurrent(seatingPlanUI);
break;
}
case EventIds.EVENT_ID_SEATSSELECTED: {
reservation =
model.reserveSeats(selectedTheater.getPrimaryKey(),
selectedMovie.getPrimaryKey(),
selectedShowTime, selectedSeats);
purchaseTicketsUI.init(model.getAccountInfo());
display.setCurrent(purchaseTicketsUI);
break;
}
case EventIds.EVENT_ID_PURCHASEREQUESTED: {
model.purchaseTickets(reservation);
purchaseCompleteUI.init(reservation.getId(),
selectedTheater.getName(),
selectedMovie.getTitle(),
selectedShowTime);
display.setCurrent(purchaseCompleteUI);
break;
}
// Other cases ...
}
} catch (Exception exception) {
// handle exceptions
}
} // end of run() method
} // end of EventDispatcher class
}
|
◆模式:模型层中的类包括所有的应用逻辑。事实上,整个J2EE服务器组件、设备中的缓存和通信类都属于模型层。模型层在客户端和服务端的复杂界面模式方面起着重要作用。
让我们看看模型层的详细内容。
|