MVC设计模式,即模型-视图-控制的设计模式,下面的这个例子是MVC模式在用户界面导航开发中所应用的开发框架,在下面这个例子中,将以电话簿为例,这个基于MIDlet的电话薄应用允许用户浏览,添加,编辑和删除联系人。
因为这个例子中MIDlet类在生命周期内只有一个实例,所以让其类实现Controller接口。
首先,定义我们需要的数据类型,即联系人Entry类:
public class Entry
{
private static int id_seq=0;
private int id;
private String name;
private String mobile;
private String phone;
private String email;
private static int nextID()
{
id_seq++;
return id_seq;
}
public Entry(String name,String mobile,String phone,String email)
{
this.id =nextID();
this.name=name;
this.mobile=mobile;
this.phone=phone;
this.email=email;
}
public int getID()
{
return id;
}
//工厂模式
public String getName()
{
return name;
}
public void setName(String updateName)
{
name=updateName;
}
.......
.......
public boolean equal(Object obj)
{
if(obj==this)
return true;
if(obj instanceof Entry)
{
return ((Entry)obj).id ==this.id;
}
return false;
}
public int hashCode()
{
return id;
}
}
在定义了需要的数据Entry后,我们在Model类实现对Entry的管理,Model类
public class Model
{
private Vector entries=new Vector();
//添加联系人
public void addEntry(Entry e)
{
entries.addElement(e);
}
//读取联系人信息
public Entry getEntry(int index)
{
return (Entry)entries.elementAt(index);
}
//更新联系人信息
public void updateEntry(Entry e)
{
for(int i=0;i<entries.size();i++)
{
Entry entry=(Entry)entries.elementAt(i);
if(entry.getID()==e.getID())
{
entry.setE_mail(e.getE_mail());
entry.setmobile(e.getMobile());
entry.setName(e.getName());
entry.setPhone(e.getPhone());
return;
}
}
}
//读取所有联系人
public Entry [] getAll()
{
Entry [] ret=new Entry[entries.size()];
entries.copyInto(ret);
return ret;
}
//返回联系人个数
public int size()
{
return entries.size();
}
//删除联系人
public void removeEntry(Entry entry)
{
for(int i=0;i<entries.size();i++)
{
Entry e=(Entry)entries.elementAt(i);
if(e.getID()==entry.getID())
{
entries.removeElementAt(i);
return ;
}
}
}
}
对于控制类Controller我们先定义为接口类型,并定义各种命令按钮,函数void handleCommand(int Command,Object obj)让实现了该接口的类具体这个方法:
public interface Controller
{
//定义各种命令含义
static final int SHOW_ADD_ENTRY=0;
static final int SHOW_EDIT_ENTRY=1;
static final int SHOW_LIST_ENTRY=2;
static final int SHOW_DETAIL_ENTRY=3;
static final int DO_ADD_ENTRY=4;
static final int DO_UPDATE_ENTRY=5;
static final int DO_REMOVE_ENTRY=6;
static final int DO_EXIT=7;
static final int OK=8;
static final int Back=9;
void handleCommand(int Command,Object obj);
}
现在我们让MIDlet这个类实现这个接口,并具体化接口的方法,实现不同视图的切换:
public class PhoneBook extends MIDlet implements Controller
{
private Display display=null;
//模型类
private Model model;
//视图类
private AddEntryUI addentryUI;
private DetailUI detailUI;
private EditEntryUI editEntry;
private ListEntryUI listEntryUI;
public PhoneBook() {
// TODO 自动生成构造函数存根
super();
display=Display.getDisplay(this);
model=new Model();
addentryUI=new AddEntryUI(this);
detailUI=new DetailUI(this);
editEntry=new EditEntryUI(this);
listEntryUI= new ListEntryUI(this);
}
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// TODO 自动生成方法存根
}
protected void pauseApp() {
// TODO 自动生成方法存根
}
protected void startApp() throws MIDletStateChangeException {
// TODO 自动生成方法存根
Entry [] all=model.getAll();
listEntryUI.load(all);
display.setCurrent(listEntryUI);
handleCommand(Controller.SHOW_ADD_ENTRY,null);
}
public void handleCommand(int Command,Object obj)
{
switch(Command)
{
case Controller.SHOW_LIST_ENTRY:
show(listEntryUI);
break;
case Controller.SHOW_ADD_ENTRY:
{
addentryUI.clear();
show(addentryUI);
}break;
case Controller.DO_ADD_ENTRY:
{
model.addEntry((Entry)obj);
refresh();
show("号码添加完成", listEntryUI);
}break;
case Controller.SHOW_EDIT_ENTRY:
{
editEntry.load((Entry)obj);
show(editEntry);
}break;
case Controller.DO_UPDATE_ENTRY:
{
Entry e=(Entry)obj;
model.updateEntry(e);
refresh();
show("信息已更新",listEntryUI);
}break;
case Controller.SHOW_DETAIL_ENTRY:
{
detailUI.load((Entry)obj);
show(detailUI);
}
break;
case Controller.Back:
{
show(listEntryUI);
}break;
case Controller.DO_REMOVE_ENTRY:
{
model.removeEntry((Entry)obj);
refresh();
show("删除成功",listEntryUI);
}break;
case Controller.DO_EXIT:
{
try {
destroyApp(true);
} catch (MIDletStateChangeException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
notifyDestroyed();
}
break;
default:;
}
}
// 提示信息
private void show(String msg, Displayable d) {
}
//更新联系人界面
private void refresh() {
}
private void show(Displayable d)
{
}
}
最后对于各种不同的视图类,我们可以根据需要实现:
编辑视图(EditEntryUI):
public class EditEntryUI extends Form implements CommandListener
{
private Command cmdOK=new Command("确定",Command.OK,1);;
private Command cmdCancel=new Command("返回",Command.BACK,1);;
private Entry entry;
private Controller controller;
private TextField name = new TextField("姓 名:", "", 20, TextField.ANY);
private TextField mobile = new TextField("移动电话:", "", 20, TextField.PHONENUMBER);
private TextField phone = new TextField("固定电话:", "", 20, TextField.PHONENUMBER);
private TextField email = new TextField("电子信箱:", "", 20, TextField.EMAILADDR);
public EditEntryUI(Controller controller)
{
super("编辑联系人");
this.controller=controller;
this.append(name);
..............
this.addCommand(cmdOK);
this.addCommand(cmdCancel);
this.setCommandListener(this);
}
public void load(Entry e)
{
.........
................
.....................
}
public void commandAction(Command c,Displayable d)
{
if(c==cmdOK)
{
......
..............
...................
}
if(c==cmdCancel)
{
...............
}
}
}
其他视图:
ListEntryUI
AddEntryUI
DetailUI
总结:对于MVC模式用于导航界面的框架,让程序更易于维护,并且很容易添加新的界面而不影响Model类,但是这种模式使得对每一个事件都需要一个唯一的标记,而且控制器中的switch-case语句会随着界面的增加而增加变得难以维护,还有Controller类引用了所有的View类,使得在程序启动的时候就被初始化,导致了较大开销。