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

02-11-16 scorpio_leon
自己的班级网站,不用什么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);
    ......
}
<p>

AbstractUser.java

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

以前这部分是直接写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();
    ......
}    

<p>

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;
	}

}

<p>

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

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

jxb8901
2002-11-16 10:17
我觉得你的类之间的职责划分好象不是很明确, User类中的getUserById(),

insert(), delete()方法应该放在UserManager类中, 如果这样getUserById

就可以是static的.

你可以参考一下Jive中的User和UserManager类, Jive中的User类只包含与某个用户有关的属性的set/get方法, 而UserManager中则包含Create,Delete,

GetUser等属于管理者的方法, 这样划分概念很明确.

我也是Java新手, 希望多探讨.

scorpio_leon
2002-11-16 10:42
谢谢!

insert,delete,update,getUserById等方法我觉得是属于User的基本原子方法

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

jxb8901
2002-11-16 14:03
我的理解是User类应该代表某一个用户, 从对象角度来理解, 它有自己的

属性和方法, 在问题域每个用户都有自己的name, id等属性这一点应该没有

争议, 另外我们可以请求一个用户修改他自己的name, 但若我们请求一个用户

create或delete(不知能否和你的User中的insert和delete对应另外一个用户

好象不合逻辑; 还有一个用户已经有一个唯一的, 你若要求一个用户根据ID

查找出另一个用户(对应getUserById)是不是也不合逻辑呢?

想听一下你觉得Insert等方法是User的"原子方法"的理由.

scorpio_leon
2002-11-17 08:28
谢谢,你说的有道理^ ^

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

insert(),update(),delete()当然只对自身了,就根据主键嘛

而getUserById我上面也说了,本应是静态方法,本不应该与实例有联系的

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

scorpio_leon
2002-11-17 16:49
对,刚才写代码的时候感觉还是按你说的,分开结构清晰一点^ ^

那么就要维护两套接口与实现了,User and UserManager

那还是涉及到静态方法的问题

或者用abstract定义UserManager,那么扩展性就要受到限制(我在想一般情况是否需要这样的灵活性)

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

jxb8901
2002-11-18 19:59
我觉得对象池一定是要的, 不过在系统开发的初期可以不考虑它, 系统的基本框架完全确定后再考虑对象池好象也不晚, 不知我的看法对不对, 希望有高手指点一二. 我现在也在做一个WEB项目, 由于客户希望尽快见到系统的样子, 有很多有关性能方面的要素我都没有考虑, 象连接池,缓冲区等我都准备在系统的基本模块完成后进行系统优化时再考虑, 不知我这样做有没有什么不妥.

scorpio_leon:我不明白你为什么一定要把Usermanager设计成接口呢?我觉得设计成抽象类也很好啊. 另外为简化起见, 我认为User可设计成值对象, 而所有有关USER的数据操作都可以放在UserManager中, 你认为呢?

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

希望大家多指点!!!

scorpio_leon
2002-11-18 23:07
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;
	}
}
<p>

iceant
2002-11-18 23:16
你的 User 可以用 CMP 啦

blues
2002-11-19 18:32
小数据量的东西,不要弄的这么复杂了.对象池真的很没有必要呀。

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

DAOFactory --为什么DAO还用一个factory呀?呵呵,说的也有道理,为了支持不同数据库。不过,真正做起来后你会发现这样做很不爽的。

支持多个数据库的情况,俺是这么做的:如果是使用标准sql(ANSI92 SQL)

就维护一套class;如果确实需要使用非标准的sql的时候再想办法用factory或其他方法来处理。

jive中访问数据库为什么要有个Factory呀?我想他不是为了支持多种数据库,而是为了支持多种数据源,象用xml文件来存储数据,这样。

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

jxb8901
2002-11-19 18:58
同意blues的观点, 我也觉得太复杂了点! 能简单尽量简单^_^

banq
2002-11-20 13:14
对象池使用取决你对系统的性能要求,如果你的程序运行在容器中,提供容器性能是首要;

scorpio_leon
2002-11-20 14:08
多谢各位,知道了 ^ ^

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

猜你喜欢