请教,这样需不需要使用对象池,这样设计有问题吗?

自己的班级网站,不用什么EJB,Struts的模式,简单的javabean+servlet+jsp,但是想设计的好一点,刚写到User部分遇到一个问题
User.java


public interface User {
public abstract User getUserById(long userid);// like a static method
public abstract int insert(Connection conn);
public abstract int delete(Connection conn);
public abstract int update(Connection conn);
public abstract long getUserid();
public abstract void setUserid(long id);
......
}

AbstractUser.java

public abstract class AbstractUser implements User {
protected long userid;
.......
public abstract User getUserById(long userid);// like a static method
......
}

以前这部分是直接写User Class的,现在改成以上的模式,但发现原来用到的静态方法不可写在Interface中,只能写成非静态的(是不是像EJB2的Home方法?)
那么在以下的UserManager需要用到很多次User中的这些"静态方法",那么我就想用一个User的静态变量来调用那些方法
UserManager.java

public class UserManager {
private static Logger logger =
(Logger) Logger.getLogger(UserManager.class.getName());
private static User USER = DAOFactory.getUser();
......
}


DAOFactory.java

public class DAOFactory {

private static Logger logger =
(Logger) Logger.getLogger(DAOFactory.class.getName());

public static User getUser() {
User user = null;
try {
InitialContext ic = new InitialContext();
String className = (String) ic.lookup(JNDINames.USER_DAO_CLASS);
user = (User) Class.forName(className).newInstance();
} catch (NamingException ne) {
logger.error("DAOFactory.getUser occured a error about JNDI name: ", ne);
} catch (Exception se) {
logger.error(
"DAOFactory.getUser occured a unknown error: ", se);
}
return user;
}

}

但我又担心这些方法中的数据在共享访问中会出现不一致,而同步这些方法开销太大了吧,那么我就是要用对象池?

不知道这样考虑是不是有必要,关于数据在共享访问,以及使用同步方面我理解不深,很不确定,谢谢解答 ^_^

我觉得你的类之间的职责划分好象不是很明确, User类中的getUserById(),
insert(), delete()方法应该放在UserManager类中, 如果这样getUserById
就可以是static的.
你可以参考一下Jive中的User和UserManager类, Jive中的User类只包含与某个用户有关的属性的set/get方法, 而UserManager中则包含Create,Delete,
GetUser等属于管理者的方法, 这样划分概念很明确.
我也是Java新手, 希望多探讨.

谢谢!
insert,delete,update,getUserById等方法我觉得是属于User的基本原子方法
放在User中也有道理呀,所以才要用interface-abstrace这样设计,就是要封装User,而UserManager只是调用User的各种方法来达到一定的目的,否则DAO的意义就不大了,或者用在另一个地方,反正我看jive的那一套还不是很好,不能说服我完全学他的,或许我看得还不够全面^ ^

我的理解是User类应该代表某一个用户, 从对象角度来理解, 它有自己的
属性和方法, 在问题域每个用户都有自己的name, id等属性这一点应该没有
争议, 另外我们可以请求一个用户修改他自己的name, 但若我们请求一个用户
create或delete(不知能否和你的User中的insert和delete对应另外一个用户
好象不合逻辑; 还有一个用户已经有一个唯一的, 你若要求一个用户根据ID
查找出另一个用户(对应getUserById)是不是也不合逻辑呢?
想听一下你觉得Insert等方法是User的"原子方法"的理由.

谢谢,你说的有道理^ ^

不过我现在只是想把User相关的最基本方法(insert....)由自身实现,其实我还不觉得分开有什么太大的好处,因为这些基本方法是由属性决定的。不过现在外面很多例子确实如你所说,应该是有一定道理的。但到我现在应用的层次还没感觉出来。

insert(),update(),delete()当然只对自身了,就根据主键嘛
而getUserById我上面也说了,本应是静态方法,本不应该与实例有联系的

可以看看那我原来提的问题吗?^ ^

对,刚才写代码的时候感觉还是按你说的,分开结构清晰一点^ ^

那么就要维护两套接口与实现了,User and UserManager
那还是涉及到静态方法的问题
或者用abstract定义UserManager,那么扩展性就要受到限制(我在想一般情况是否需要这样的灵活性)

我看了,用org.apache.commons.pool包还可以很方便解决数据池的问题,所以UserManager设计成接口也不是很麻烦,大家怎么认为呢?

我觉得对象池一定是要的, 不过在系统开发的初期可以不考虑它, 系统的基本框架完全确定后再考虑对象池好象也不晚, 不知我的看法对不对, 希望有高手指点一二. 我现在也在做一个WEB项目, 由于客户希望尽快见到系统的样子, 有很多有关性能方面的要素我都没有考虑, 象连接池,缓冲区等我都准备在系统的基本模块完成后进行系统优化时再考虑, 不知我这样做有没有什么不妥.
scorpio_leon:我不明白你为什么一定要把Usermanager设计成接口呢?我觉得设计成抽象类也很好啊. 另外为简化起见, 我认为User可设计成值对象, 而所有有关USER的数据操作都可以放在UserManager中, 你认为呢?

还补充一点, getUserById方法若放在User中可能作为静态方法还说的过去,但若放在UserManager中就不应该作为静态方法, 其一是不合逻辑(我只会说这个词), 其二是有利于代理的权限验证, 若设计为静态方法, 该如何验证请求者的权限呢?

希望大家多指点!!!

UserManager设计为接口是为了以后好扩展(也许不一定会用到),因为用抽象类后,以后增加功能时只能用继承,比较受限制,而且,如果有公共方法的需求,可以再用抽象来配合接口,只是静态方法这个问题有点麻烦。

你说的不合逻辑我不理解。
至于权限控制,不一定要在底层控制呀,我可以在外层控制,我是觉得底层应该重在结构,不会经常变化,所以设计的灵活点好。

呵呵,我的UserManagerSessionBean已经按这些思路写好了,包括对象池,外面应该还会再套一层UI层,那里应该有权限的控制,请指点
UserManagerSessionBean.java


package com.bba96.web.session;

import java.sql.Connection;
import java.sql.Date;
import java.sql.Timestamp;

import org.apache.log4j.Logger;

import com.bba96.util.ConnectionManager;
import com.bba96.util.GlobalVariable;
import com.bba96.util.Sequence;
import com.bba96.web.exception.InvalidPoolException;
import com.bba96.web.model.base.User;
import com.bba96.web.model.base.UserManager;
import com.bba96.web.model.base.UserManagerPool;
import com.bba96.web.model.base.UserPool;

/**
*
* Class/Interface description
*
* @author: scorpio_leon
* @time: 2002-11-15 19:48:08
*
*/

public class UserManagerSessionBean {
private static Logger logger =
(Logger) Logger.getLogger(UserManagerSessionBean.class.getName());

/**
* Method loginCheck.
* @param username
* @param password
* @return int:
* 0 login success;
* 1 password error;
* 2 Object in pool can not be got;
* 3 password right but set user state error.
* -1 unknown error
*/

public int loginCheck(String username, String password) {
int result = -1;
User user = null;
UserManager userManager = null;
Connection conn = null;
try {
userManager = UserManagerPool.getUserManager();
conn = ConnectionManager.getConnection();
user = userManager.getUserByName(username, conn);
if (user != null) {
if (password.equals(user.getPassword())) {
user.setLoginCount(user.getLoginCount() + 1);
user.setLoginTime(new Timestamp(System.currentTimeMillis()));
int update = userManager.updateUser(user, conn);
if (update != 0) {
result = 3;
} else {
result = 0;
}
} else {
result = 1;
}
}
} catch (InvalidPoolException ipe) {
logger.error(
"Some Object in ObjectPool can not be got!", ipe);
result = 2;
} catch (Exception e) {
logger.error(
"checkLogin error:", e);
result = -1;
} finally {
UserManagerPool.releaseUser(userManager);
ConnectionManager.closeConnection(conn);
}
return result;
}

/**
* Method createUser.
* @param username
* @param password
* @param email
* @return int:
* 0 create User success;
* 2 Object in pool can not be got;
* -1 unknown error
*/

public int createUser(String username, String password, String email) {
int result = -1;
User user = null;
UserManager userManager = null;
Connection conn = null;
try {
userManager = UserManagerPool.getUserManager();
conn = ConnectionManager.getConnection();
user = UserPool.getUser();
user.setUserid(Sequence.getId(
"user", conn));
user.setUsername(username);
user.setPassword(password);
user.setEmail(email);
user.setEmailVisible(false);
user.setNickname(GlobalVariable.DEFAULT_NORMAL_STRING);
user.setLoginCount(1);
user.setLoginTime(new Timestamp(System.currentTimeMillis()));
Date date = (java.sql.Date)(new java.util.Date());
user.setCreationDate(date);
user.setModifiedDate(date);
user.setFrom(GlobalVariable.DEFAULT_NORMAL_STRING);
user.setBirthday(GlobalVariable.DEFAULT_SQL_DATE);
user.setHomepage(GlobalVariable.DEFAULT_NORMAL_STRING);
user.setMsn(GlobalVariable.DEFAULT_NORMAL_STRING);
user.setYm(GlobalVariable.DEFAULT_NORMAL_STRING);
user.setOicq(GlobalVariable.DEFAULT_NORMAL_STRING);
user.setIntroduce(GlobalVariable.DEFAULT_NORMAL_STRING);
user.setSignature(GlobalVariable.DEFAULT_NORMAL_STRING);
user.setPermission(GlobalVariable.DEFAULT_USER_PERMISSION);
user.setState(GlobalVariable.DEFAULT_USER_STATE);
result = userManager.createUser(user, conn);
} catch (InvalidPoolException ipe) {
logger.error(
"Some Object in ObjectPool can not be got!", ipe);
result = 2;
} catch (Exception e) {
logger.error(
"createUser error:", e);
result = -1;
} finally {
UserPool.releaseUser(user);
UserManagerPool.releaseUser(userManager);
ConnectionManager.closeConnection(conn);
}
return result;
}
}

你的 User 可以用 CMP 啦

小数据量的东西,不要弄的这么复杂了.对象池真的很没有必要呀。

关于User类,操作和属性 分开更合适。这有点象valueObject/DAO的关系。

DAOFactory --为什么DAO还用一个factory呀?呵呵,说的也有道理,为了支持不同数据库。不过,真正做起来后你会发现这样做很不爽的。
支持多个数据库的情况,俺是这么做的:如果是使用标准sql(ANSI92 SQL)
就维护一套class;如果确实需要使用非标准的sql的时候再想办法用factory或其他方法来处理。
jive中访问数据库为什么要有个Factory呀?我想他不是为了支持多种数据库,而是为了支持多种数据源,象用xml文件来存储数据,这样。

//你这么想套用设计模式,如果你是在校学生,那也很难得:)

同意blues的观点, 我也觉得太复杂了点! 能简单尽量简单^_^

对象池使用取决你对系统的性能要求,如果你的程序运行在容器中,提供容器性能是首要;

多谢各位,知道了 ^ ^

BTW:看来我的用户与权限的关系还有很多没有设计好,再继续跟大家学吧。