转载:http://www.cnblogs.com/macooma/archive/2010/04/28/1723173.html

看了这篇文章,对LWUIT的 MVC 模式有了部分了解,看来以前的认识是错误的,就像文章最后那段代码

MVC 是一个优秀的体系结构设计模式。MVC 把软件系统分为三个基本部分:模型(Model),视图(View)和控制器(Controller)。如下图所示:

上图对 MVC 模式做了简单解释,明白了上图对 MVC 的各个划分部分的职责就很容易理解了。模型(Model)又称“数据模型”(Model),用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“模型”有对数据直接访问的权力,例如对数据库的访问。“模型”不依赖“视图”和“控制器”,也就是说,模型不关心它会被如何显示或是如何被操作。但是模型中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此模型的视图必须事先在此模型上注册,从而,视图可以了解在数据模型上发生的改变。
视图(View)又称视图层,能够实现数据有目的的显示(理论上,这不是必需的)。在视图中一般没有程序上的逻辑。为了实现视图上的刷新功能,视图需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那里注册。
控制器(Controller)起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据模型上的改变。
Swing MVC 是公认的 MVC 设计的典范,Swing 的各个可视化组件都使用 MVC 模式来设计。在 Swing 中,M(Model,数据模型)是 JTextField 的 Document,JTabel 的 TableModel,JTree 的 TreeModel 。。。V(View,视图)则是 ComponentUI。C(控制器,Controller)却不是很明显,可以简单地将其 Event 机制看做一个 Swing 团队开发给 Swing 程序员的 C。
LWUIT 引入了 MVC 的设计思想,其实 LWUIT 就是一个 JavaME 的 MVC 框架,LWUIT 官方就把 Swing Like MVC 列在了其主要特征的第二位。了解了 Swing 的 MVC 之后,参照 LWUIT 的 API,我想你可以将 LWUIT 的 M、V、C 对号入座了吧?没错,正如你所猜到的,在 LWUIT 中,M(Model,数据模型)是 List 的 ListModel,Tabel 的 TableModel,Tree 的 TreeModel 。。。V(View,视图)则是 ComponentUI(即 API 中给的各个 LWUIT 控件)。C(控制器,Controller)却不是很明显,可以简单地将其 Event 机制看做一个 LWUIT 团队开发给 LWUIT 程序员的 C。如果你觉得这样说对控制器的理解很抽象,你可以把你的程序里每个实现了 com.sun.lwuit.events.ActionListener 接口的类当成一个控制器。
MVC 的优势就是各司其责:M 只管把数据组织好就是了;V 只管把信息完美地展现给用户;而 C 则只负责对用户事件进行监听,并做出相应处理,它是 MVC 的组织者。这让人想起来流行的 Java EE 四层体系架构:展现层、业务层、数据访问层(操作保存数据库)、持久层(数据保存为文件),各层各司其职。那是以业务模型为中心的大型应用,我们的 JavaME 只是手机客户端的应用小程序,没有那么复杂的业务逻辑要处理,也没有庞大的业务数据要持久化,没有必要分那么多层,就一个表现层足够了。也可以根据需要适当把模型层扩展一下。如下图所示,对使用了 LWUIT 的 Java ME 应用程序中责任分工做的一个概述。

上图对 MVC 模式做了简单解释,明白了上图对 MVC 的各个划分部分的职责就很容易理解了。模型(Model)又称“数据模型”(Model),用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“模型”有对数据直接访问的权力,例如对数据库的访问。“模型”不依赖“视图”和“控制器”,也就是说,模型不关心它会被如何显示或是如何被操作。但是模型中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此模型的视图必须事先在此模型上注册,从而,视图可以了解在数据模型上发生的改变。        视图(View)又称视图层,能够实现数据有目的的显示(理论上,这不是必需的)。在视图中一般没有程序上的逻辑。为了实现视图上的刷新功能,视图需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那里注册。        控制器(Controller)起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据模型上的改变。        Swing MVC 是公认的 MVC 设计的典范,Swing 的各个可视化组件都使用 MVC 模式来设计。在 Swing 中,M(Model,数据模型)是 JTextField 的 Document,JTabel 的 TableModel,JTree 的 TreeModel 。。。V(View,视图)则是 ComponentUI。C(控制器,Controller)却不是很明显,可以简单地将其 Event 机制看做一个 Swing 团队开发给 Swing 程序员的 C。        LWUIT 引入了 MVC 的设计思想,其实 LWUIT 就是一个 JavaME 的 MVC 框架,LWUIT 官方就把 Swing Like MVC 列在了其主要特征的第二位。了解了 Swing 的 MVC 之后,参照 LWUIT 的 API,我想你可以将 LWUIT 的 M、V、C 对号入座了吧?没错,正如你所猜到的,在 LWUIT 中,M(Model,数据模型)是 List 的 ListModel,Tabel 的 TableModel,Tree 的 TreeModel 。。。V(View,视图)则是 ComponentUI(即 API 中给的各个 LWUIT 控件)。C(控制器,Controller)却不是很明显,可以简单地将其 Event 机制看做一个 LWUIT 团队开发给 LWUIT 程序员的 C。如果你觉得这样说对控制器的理解很抽象,你可以把你的程序里每个实现了 com.sun.lwuit.events.ActionListener 接口的类当成一个控制器。        MVC 的优势就是各司其责:M 只管把数据组织好就是了;V 只管把信息完美地展现给用户;而 C 则只负责对用户事件进行监听,并做出相应处理,它是 MVC 的组织者。这让人想起来流行的 Java EE 四层体系架构:展现层、业务层、数据访问层(操作保存数据库)、持久层(数据保存为文件),各层各司其职。那是以业务模型为中心的大型应用,我们的 JavaME 只是手机客户端的应用小程序,没有那么复杂的业务逻辑要处理,也没有庞大的业务数据要持久化,没有必要分那么多层,就一个表现层足够了。也可以根据需要适当把模型层扩展一下。如下图所示,对使用了 LWUIT 的 Java ME 应用程序中责任分工做的一个概述。

MVC 可以使我们应用程序的表现层部分更加低耦合、高内聚、灵活度更高。那么我们在 LWUIT 程序中应该怎样使用 MVC 模式呢?

1、Form 或者其他顶层容器中,由各个 LWUIT 组件构成了 View 视图层。用来展现数据,提供用户操作的图形界面。

2、一个或者一组业务对象是 Model。它们存放了 LWUIT 组件要显示的数据。它们是业务对象,因此,可以直接在业务层代码中使用,执行复杂的业务计算。为了让 LWUIT 组件实时展现业务对象的数据,我们需要让 LWUIT 组件监听业务对象,一旦业务对象发生改变,就重新根据新的数据,构建新的 LWUIT 组件的 Model,从而在 LWUIT 组件上展现最新的业务对象数据。为了让业务对象能够得到用户最新输入的数据,我们还需要将业务对象注册到 LWUIT 组件上。一旦 LWUIT 组件的数据发生了改变,就通知业务对象。业务对象根据 LWUIT 组件的 Model,修改业务对象的值。

3、在 LWUIT 各个组件上注册响应事件的监听器(控制器),以响应用户的操作。

于是 MVC 后的 LWUIT 程序的执行流程就是这个样子了:用户看到一个 LWUIT 控件构成的界面 -> 用户在界面上进行操作 -> LWUIT 控件的控制器被触发 -> 可能就激发了 ActionListener 的事件,引起业务对象自动使用 LWUIT 的 Model 数据进行更新 ->  业务对象更新数据,又会激发业务对象上的 DataChangedListener 的事件,这会引起所有监听业务对象 LWUIT 控件更新其 Model 的数据,从而改变 LWUIT 控件的显示 -> 我们可能针对业务对象,执行业务层代码,进行复杂的业务计算,从而得到新的业务对象的值,这同样会激发业务对象的 DataChangedListener 的事件,让 LWUIT 控件的 Model 得到更新,从而改变 LWUIT 控件显示的界面 -> 当然,我们也可以直接修改某些 LWUIT 组件的 Model 或者外观。

可以看出,通过业务对象和 Lwuit 控件的 Model 关联起来,在 LWUIT 应用程序中只需要“以业务对象为中心”,操纵业务对象,执行业务操作就可以了。

List 控件是最常用的 LWUIT 控件,因为我们的手机屏幕总是受限的。关于 List 我们前面的博客中有过接触——《玩转 LWUIT 之四:LWUIT 控件(中)》里介绍的 ComboBox 就是一个 List 的子类。我们写一个关于 List 的 MVC 应用。仍然使用 LWUIT 官方提供的开发指南中给的 List 使用的例子。源代码如下(当然实际运用中要复杂一些):

1 package com.defonds.lwuit;
2
3  import com.sun.lwuit.Button;
4  import com.sun.lwuit.CheckBox;
5  import com.sun.lwuit.Command;
6  import com.sun.lwuit.Component;
7  import com.sun.lwuit.Display;
8  import com.sun.lwuit.Form;
9  import com.sun.lwuit.List;
10  import com.sun.lwuit.animations.CommonTransitions;
11  import com.sun.lwuit.events.ActionEvent;
12  import com.sun.lwuit.events.ActionListener;
13  import com.sun.lwuit.events.DataChangedListener;
14  import com.sun.lwuit.layouts.FlowLayout;
15  import com.sun.lwuit.list.DefaultListModel;
16  import com.sun.lwuit.list.ListCellRenderer;
17  import com.sun.lwuit.list.ListModel;
18  import com.sun.lwuit.plaf.UIManager;
19  import com.sun.lwuit.util.Resources;
20
21  public class HelloMidlet extends javax.microedition.midlet.MIDlet implements DataChangedListener{
22
23 private Form exampleContainer;// declare a Form
24   private String[] content = { "Red", "Blue", "Green", "Yellow" };//just a data source demo,of course,the data can be from the network,storage etcetera...
25   private int contentLeng = 4;//remeber the size of content
26   private ListModel myListModel;//declare a ListModel
27   private ListModel myListModel2;//declare a ListModel
28   private List list;//declare a List
29   private List list2;//declare a List
30   private Button button;//declare a Button
31  
32 public void startApp() {
33 // init the LWUIT Display
34   Display.init(this);
35 // Setting the application theme is discussed
36 // later in the theme chapter and the resources chapter
37   try {
38 Resources r = Resources.open("/myresources.res");
39 UIManager.getInstance().setThemeProps(r.getTheme("myresources"));
40 } catch (java.io.IOException e) {}
41
42 exampleContainer = new Form("Form Title");// Create a Form
43 myListModel = new DefaultListModel(content);//Initialize a default list model with "content" inside
44 myListModel.addDataChangedListener(this);//Adding a a data changed listener to catch user operation
45 myListModel2 = new DefaultListModel();//Initialize a default list model with nothing inside
46 myListModel2.addItem("White");//add an item to model
47 myListModel2.addItem("Black");//add an item to model
48
49 button = new Button("Move selected item down");// Create a Button
50 button.setAlignment(Component.CENTER);//Sets the Alignment of the button
51 button.addActionListener(new ActionListener(){
52 public void actionPerformed(ActionEvent evt) {
53 myListModel.removeItem(list.getSelectedIndex());
54 }
55 });
56
57 list = new List(myListModel);//Creating a List with "myListModel"
58 list2 = new List(myListModel2);//Creating a List with "myListModel2"
59 list.setListCellRenderer(new checkBoxRenderer());//Setting a checkBox renderer
60 list2.setListCellRenderer(new checkBoxRenderer());//Setting a checkBox renderer
61
62 exampleContainer.setLayout(new FlowLayout());//Set LayoutManager
63 exampleContainer.addComponent(list);//Add a List to the Form content pane
64 exampleContainer.addComponent(button);//Add a Button to the Form content pane
65 exampleContainer.addComponent(list2);//Add a List to the Form content pane
66 exampleContainer.setTransitionOutAnimator(CommonTransitions.createFade(400));//Set Transitions animation of Fade
67 exampleContainer.addCommand(new Command("Run", 2));//Add Command key
68 exampleContainer.show();//Show it
69 }
70
71 public void pauseApp() {}
72
73 public void destroyApp(boolean unconditional) {}
74
75 //implements the method of DataChangedListener
76 public void dataChanged(int type, int index) {
77 myListModel2.addItem(content[index]);//add the deleted item to myListModel2
78 while(index < contentLeng - 1){
79 content[index] = content[++ index];
80 }
81 content[index] = null;
82 contentLeng --;//refresh the content to synchronize with myListModel
83 exampleContainer.refreshTheme();//refresh the form theme
84 }
85
86 /**
87 * Demonstrates implementation of a renderer derived from a CheckBox
88 */
89 private static class checkBoxRenderer extends CheckBox implements ListCellRenderer{
90 /** Creates a new instance of checkBoxRenderer */
91 public checkBoxRenderer(){
92 super("");
93 }
94
95 // Setting the current check box text and status
96 public Component getListCellRendererComponent(List list,
97 Object value, int index, boolean isSelected) {
98 setText("" + value);
99 if (isSelected){
100 setFocus(true);
101 setSelected(true);
102 }else{
103 setFocus(false);
104 setSelected(false);
105 }
106 return this;
107 }
108
109 // Returning the list focus component
110 public Component getListFocusComponent(List list) {
111 setText("");
112 setFocus(true);
113 setSelected(true);
114 return this;
115 }
116 }
117 }
118

HelloList 运行效果图如下所示:

这段代码的运行效果是当选择了上方 List 中的选项后,点击“Move selected item down”按钮可以把该选项转移到下方 List 中。限于美工底子有限,UI 效果有点差,这里重点演示 MVC 效果。比如连续点击两次“Move selected item down”后运行效果图如下:

用户选择用户操作后(按了“Move selected item down”按钮),控制器被触发(按钮所添加的 ActionListener),激发了 ActionListener 的事件,引起业务对象自动使用 LWUIT 的 Model 数据进行更新(就是代码中把某项 remove 掉),业务对象更新数据,又会激发业务对象上的 DataChangedListener 的事件(监听于 myListModel 的 DataChangedListener 被激发),引起所有监听业务对象的 DataChangedListener 的事件(dataChanged 方法被调用),让 LWUIT 控件的 Model 得到更新(myListModel2 被更新),从而改变 LWUIT 控件显示的界面。

从代码中可以看出,ListModel 是 Model,List、ListCellRenderer 是 View,可以把继承自 ActionListener 的 类作为 Controller。有的朋友把自己写的一个封装信息的 JavaBean 当做 Model,把 List 当做 View,而把 ListCellRenderer 当做是 Controller,其实是不对的,是对 LWUIT MVC 的误解,虽然写出来的代码运行应该是没有问题的。比如下边一段代码:

1 /**
2 * Model
3 */
4 public class Person {
5 private String name;
6 private Image photo;
7 public Person(String name, Image photo) {
8 this.name = name;
9 this.photo = photo;
10 }
11 public String getName() {
12 return name;
13 }
14 public void setName(String name) {
15 this.name = name;
16 }
17 public Image getPhoto() {
18 return photo;
19 }
20 public void setPhoto(Image photo) {
21 this.photo = photo;
22 }
23 }
24 /**
25 * View
26 */
27 public List createList(Person[] persons, int orientation, ListCellRenderer renderer) {
28 List list = new List(persons);
29 list.setListCellRenderer(renderer);
30 list.setOrientation(orientation);
31 return list;
32 }
33
34 /**
35 * Controller
36 */
37 class Renderer extends Container implements ListCellRenderer {
38 public Label name = new Label("");
39 public Label pic = new Label("");
40 public Label focus = new Label("");
41 public Container cnt = new Container(new BoxLayout(BoxLayout.Y_AXIS));
42 public Renderer() {
43 setLayout(new BorderLayout());
44 addComponent(BorderLayout.WEST, pic);
45 name.getStyle().setBgTransparency(0);
46 cnt.addComponent(name);
47 addComponent(BorderLayout.CENTER, cnt);
48 //focus用于设置List选中时的效果,这里设置List的选中项具有绿色的边框
49 focus.getStyle().setBorder(Border.createLineBorder(1, 0x00ff00));
50 }
51 public Component getListCellRendererComponent(List list, Object value,
52 int index, boolean isSelected) {
53 Person person = (Person) value;
54 name.setText(person.getName());
55 pic.setIcon(person.getPhoto());
56 return this;
57 }
58 public Component getListFocusComponent(List list) {
59 return focus;
60 }
61 }

转载于:https://www.cnblogs.com/datong/archive/2010/06/30/1768326.html

深入理解 LWUIT 框架的 MVC相关推荐

  1. 浅谈javaweb三大框架和MVC设计模式

    浅谈javaweb三大框架和MVC设计模式 转载自:http://blog.csdn.net/sunpeng19960715/article/details/50890705 小序:博主以前在学jav ...

  2. 架构(三层架构)、框架(MVC)、设计模式三者异同点

    前言: 本博客主要针对架构.框架和设计模式三者的差别.还有三层和MVC的差别进行讨论.对于这三者一点都不了解的.请点在维基和百度百科上补补课.这里就不发链接了 软件架构(software archit ...

  3. 框架模式MVC与MVP在Android中的应用

    很多人在开发Android项目时没有考虑过架构模式的问题,以至于随着项目的增大,Activty或者Fragment中代码也会越来越多,导致项目的维护变的越来越复杂.然而在Android中使用比较多的两 ...

  4. 框架模式 MVC 在Android中的使用

    算来学习Android开发已有2年的历史了,在这2年的学习当中,基本掌握了Android的基础知识.越到后面的学习越感觉困难,一来是自认为android没啥可学的了(自认为的,其实还有很多知识科学), ...

  5. ASP.NET开源MVC框架Vici MVC(三)HELLO WORD

    ASP.NET开源MVC框架Vici MVC 最大的特点是支持ASP.NET2.0  iis不需要额外的设置 官方实例下载地址http://viciproject.com/wiki/Projects/ ...

  6. php中的控制器是什么意思,理解PHP中的MVC编程之控制器_php

    简单来讲,控制器的作用就是接受请求.它使用获取的方法,在这里是通过URI,载入一个功能模块来刷新或者提交一个表述层.控制器将使用$_GET自动全局变量来判断载入哪一个模块. 一个请求的例子,看起来像这 ...

  7. 从Java的角度理解前端框架,nodejs,reactjs,angularjs,requirejs,seajs

    从Java的角度理解前端框架,nodejs,reactjs,angularjs,requirejs,seajs [前端神秘的面纱] 对后端开发来说,前端是神秘的, 眼花缭乱的技术,繁多的框架, 如果你 ...

  8. 深入理解 Flutter 框架层次结构

    作者: Frederik Schweiger 链接 : The Layer Cake Flutter 是一个非常优秀的跨平台开发框架,基于 Flutter 我们可以用很少的代码快速的开发出界面精美的 ...

  9. spring框架_一篇文章带你理解Spring框架

    虽然现在流行用SpringBoot了,很多配置已经简化和封装了,但是对于Spring的一些基础我们了解一些是对我们自己的架构思想很有帮助的!接下来和笔者一起来探讨一下Spring框架吧! 1.什么是S ...

最新文章

  1. Android获取顶部状态栏statusBar高度、底部导航栏navigationBar高度
  2. Java I/O流-总结(InputStream,OutputStream,Reader,Writer)
  3. windows备份0x80070422错误解决方法
  4. 物料主数据(MM03)跳转函数
  5. 1051 复数乘法(PAT乙级 C++)
  6. AI如何提升10倍筛药效率?6月18日华为云携手中科院上海药物所揭开谜底
  7. 怎么理解高内聚低耦合
  8. 《代码大全》程序员们怎样花费自己的时间
  9. 利用jquery写的从后台获取json数据以表格显示,并带翻页功能.里面包含模式窗口等功能...
  10. 问题:Cannot assign a device for operation Variable
  11. codevs——1044 拦截导弹(序列DP)
  12. Java代码质量改进之:使用ThreadLocal维护线程内部变量
  13. 数据库,可不只是 CRUD!
  14. python pytorch tenser 索引 slice 切片
  15. 数据标准化/归一化normalization
  16. java mpp转图片,Java使用mpxj导入.mpp格式的Project文件(甘特图)
  17. 如何消除你的情绪、戾气与恶念
  18. Monte Carlo tree search 学习
  19. LINUX学习-在LCD上显示多行文字
  20. linux 解压所有以zip结尾的文件_Linux下的压缩zip,解压缩unzip命令详解及实例

热门文章

  1. 小程序步数解密php,微信小程序--获取微信运动步数的实例代码
  2. 智能路由器要成功 该怎样修炼穿墙术?
  3. C primer plus 复习题答案(上)
  4. Python pip时遇到的no moudle问题
  5. 鹏鹏:python 机器学习初学者 三剑客介绍。
  6. 简洁大气的资源网站emlog模板
  7. 解决LaTeX中的\pdfendlink ended up in different nesting level than \pdfstartlink.问题
  8. iOS直播:评论框与粒子系统点赞动画
  9. CTF高手教你如何实现文件加解密破解
  10. 2019世界移动通信大会--中国5G迎来高光时刻