Model
与数据库,框架和开发方式无关
知识产权保护请从我做起,转载请注明出处。
http://blog.youkuaiyun.com/struts2
代码示例请参看:http://code.google.com/p/mdx-shopping
概述
说到Model就不得不提软件开发领域著名的构架模式:MVC。
MVC是一种软件构架,现在被认为是软件工程中使用的一种构架模式.这个模式将域逻辑(用户使用的应用程序逻辑)从用户界面(输入和表示)中分离出来,从而可以独立开发、测试和维护每一部分(关注分离)。
原文参看:
http://en.wikipedia.org/wiki/Model%E2%80%93View%E2%80%93Controller
MVC这三个字母风别是Model,View和Controller的首字母,一下这边文章主要探讨一下什么是Model,如何设计和实现Model。
Model是什么
Model是什么:
要回答Model是什么,需要从理解Model的定义开始。
根据MVC的定义,Model是域逻辑,或者可以通俗地理解为用户需要使用的应用程序的逻辑,或者跟简单一些就是用户的需求。
用户需求通常包含两部分的内容,做什么操作和得到什么结果。
做什么操作就是需要帮助用户完成什么业务逻辑,毕竟软件的初衷就是帮助客户完成一些原本用户需要重复做的事情。
得到什么结果就是做完用户期望的操作之后,得到什么结果,或许这才是用户最期望的内容,通常情况下这些内容需要被保存下来。
概括起来说,Model就是用户操作和被操作的数据的结合体。
Mode不是什么:
(1) Model是数据库吗?
简单地回答,不是。不过上面说过Model通常需要被存储起来,以供客户使用。而数据库又是最常见的数据存储的手段,所以可以这样说,Model的数据部分需通常存储在数据库中。
(2) Model可以不包含用户逻辑吗?
通常情况下不可以。Model不进包含数据,也包含对这些数据的有意义的业务操作,只有数据结合了这些有意义的操作才真正成为了Model。没有业务逻辑的数据其实已经退化为了VO或者DTO。
总结:
Model是业务逻辑和数据的结合体。业务逻辑体现了客户期望做什么,而数据体现了客户通过期望的操作想得到什么。
实例分析:
以下以用户管理为例,分析一下在这个Case中Model到底是什么。
通常的用户管理包含两个角色,第一是用户本身,第二是管理用户的管理员。
而需要做的操作可以按照角色的不同来分组:
l 对于用户本身来说,期望能够注册为系统的一个用户,希望能够使用注册用户登陆系统,同时希望能够定期修改密码。
l 对于管理员来说,希望能够了解总共有多少个用户,最好能够将用户分组管理,如果能够禁用默写用户就更好了。
在理解了这些需求的基础上,我们下面分析这个Case中的Mode。
业务逻辑(或者可以说是操作)部分:
l 用户:注册,登陆,修改密码
l 管理员:查看所有用户,用户分组,启用和禁用用户。
数据部分:
根据常规的情况,至少需要用户登录名,密码和是否有效三个数据。
所以在用户管理的Case下,Model可以理解为:
现在可以点题了,Mode就是用户通常使用的操作和期望得到的结果,可以操作可以通过BS结构来完成,也可以通过CS结构来完成,可以存储在数据库中,也可以存储在文件系统中,可以使用Struts也可以不使用Struts而直接使用Servlet。可以给予J2EE当然也可以基于.NET平台。
Mode的实现
尽管Model并不依赖于任何框架或者技术,但是为了讨论的方便,我们还是做了以下假定,在一下假定的范围内讨论Model的实现
l 使用Java语言
l Model的数据部分保存在数据库中
l 使用MyBatis来简化数据保存的操作
Model实现的两种方式:
l Manager(逻辑) + VO(数据):这种方式将数据与操作隔离,所有的操作都由Manager来完成,而VO通常承担了数据传输对象的作用,用来在前台View和Manager之间,以及Manager和数据库之间传递数据。本文中不详细讲解这种方式,这种方式较为普遍,请各位自行查阅。
l Model(逻辑+数据):这种方式注重数据与操作的整合,一下主要探讨这种方式。
实例分析:
仍旧以用户管理为例逐步分析Model的实现。
第一步,数据部分首先应该添加在Model中,这部分内容比较简单,参看以下代码:
public class LoginInfoData extends ModelObject {
private String username;
private String password;
private boolean isActive;
// getter method and setter method
}
第二部,将操作封装在Model中。但是在封装用户操作之前还有一个问题需要说明。用户操作分为两类,第一类,无中生有,第二类,有则改之。
无中生有最典型的操作是查看所有用户,而有则改之最典型的操作是修改密码。由于无中生有通常不是对某个单独的对象进行操作,所以通常设计为静态的类方法,而有则改之通常是对某一个具体实例的操作,所以通常设计为实例方法。参看以下代码:
public class LoginInfo extends LoginInfoData {
/**
* register user and connect role of user to him.
* @return true for success, false else
*/
public boolean register() {
//...
}
public static List<LoginInfo> getAll() {
//
}
}
其他的通用方法:
对于单个对象的CRUD通常应该以一种共同的方式实现,或者使用代码自动生成。请注意上述代码的继承层次关系。
Mode使用:
用户登录
protected boolean checkUserLoginInfo() {
LoginInfo info = new LoginInfo();
info.setUsername(getModel().getUsername());
if (info.load() &&
info.getPassword().equals(Digester.crypt(getModel().getPassword()))) {
// add role id and role
this.loginInfo = info;
return true;
} else {
return false;
}
}
密码修改:
public String changePassword() {
log.debug("enter customer/changepwd action, model:" + model);
// 1. check password and repassword
if (!model.getPassword().equals(model.getRePassword())) {
return INPUT;
}
// 2. check old password
LoginInfo info = new LoginInfo();
info.setUsername(getModel().getUsername());
if (!info.load() || !info.getPassword().equals(Digester.crypt(getModel().getPassword()))) {
// old user not exist or old password not equals
return INPUT;
}
// 3. generate new password hash
String newpwd = Digester.crypt(model.getPassword());
info.setPassword(newpwd);
// 4. update login info
info.update();
log.debug("update password successfully!");
return SUCCESS;
}