[color=#FF0000][/color]由于经验很少,所以每每遇到程序设计时总是很伤头脑,而最终也往往只能整出个差劲的设计来。
问题1:我设计的常用模块(比如控制台打印、字符集转换过滤、格式化日期、日志文件读写、properties文件读写、javaMail、jsonString读取、excel读取、验证码生成)等等模块经常用私有化构造方法+全部静态化方法来设计这些工具类,这样使用起来就是类名+方法名来使用,请问这种设计方法有何利弊?(tij里曾说过:当你的程序充斥着过多的static时,或许你该想想换个设计了,且实际调用起来越看越像面向过程,虽然用起来时确实方便,不用新建实例)
问题2:我的设计中经常用到抽象类,但却极少用到接口,这正常么?(我的理解是:接口就是抽象类更纯粹的一种表现,但意义是一样的,就是规范了一系列对象的所有动作,使使用这些服务的调用端可以和实际的实现相分离。)
问题3:我为程序中的业务模型层、dao层分别建立了一个工厂,这个工厂以业务模型的名称或代号为参数,以switch\catch的方式去判断并返回所求的实例,但总觉得switch\catch相当臃肿,也觉得,工厂模式除了将对象的创建工作集中到了一处进行统一管理的同时,工厂自己也是够复杂的,尤其是什么工厂方法模式和抽象工厂模式。
-------------------------------------------------------------------------
希望各位前辈能发表下对我这些看法、想法和设计思想的建议和批判,由于程序规模一直不大,且一直没有涉及到过多的修改和扩展,所以无法体会到当前设计是否足够方便扩展和修改。
------解决方案--------------------
接口比抽象类更应该值得取用:
抽象类的优势是子类继承父类方法,这是选择抽象类大于接口的唯一一个说服力原因
至于其他方面,从设计方面讲,接口的优势大于抽象类
------解决方案--------------------
同意楼上
使用接口
关于设计模式
慢慢学习
------解决方案--------------------
------解决方案--------------------
接口可以说是一个标准,抽象类到子类只能说是功能的进一步加强或更改。如果你要做消息传递的话还是得用接口的吧
------解决方案--------------------
楼主多看看开源的工程(HIBERNATE,STRUTS)
帮助会很大的
------解决方案--------------------
使用抽象类的场景:
有些方法写一次即可,后来的子类中不需要重写
然后在真正用的地方,继承你的子类,就可以使用抽象类中的已实现的方法。
而接口,它的方法在实现类中都需重写,它适用于需要不同实现的时候
将共有的方法在抽象类中实现,方法的实现不一样就声明成abstract,子类再去一一重写。抽象类一般用在工具类之类的
而service层一般用接口
现贴出我们项目里非常好的设计,使用抽象类的代码
- Java code
public abstract class AbstBaseQuerySpec implements HibernateCallback, Serializable { /** 当前页码数 */ protected Paginate paginate = new Paginate(); /** 是否需要分页支持 */ protected boolean paginary = true; /** * 重置查询条件 */ public void resetSpec() { paginate.reset(); reset(); } public Object doInHibernate(Session session) throws HibernateException, SQLException { return null; } protected void applyNamedParameterToQuery(Query queryObject, String paramName, Object value) throws HibernateException { if (value instanceof Collection) { queryObject.setParameterList(paramName, (Collection) value); } else if (value instanceof Object[]) { queryObject.setParameterList(paramName, (Object[]) value); } else { queryObject.setParameter(paramName, value); } } /** * reset spec */ protected abstract void reset(); /** * 执行查询后,通过此方法取得分页信息 * * @return */ public Paginate getPaginate() { return paginate; } /** * @param paginate * The paginate to set. */ public void setPaginate(Paginate paginate) { this.paginate = paginate; } /** * @param paginary * The paginary to set. */ public void setPaginary(boolean paginary) { this.paginary = paginary; }}// 基于Hibernate查询规则限定条件public abstract class AbstQueryStringSpec extends AbstBaseQuerySpec { /** */ private Map<String, Object> params = new HashMap<String, Object>(); /** * Named hql queryName * * @return */ public abstract String queryString(); /** * * @param session * @return * @throws HibernateException * @throws SQLException * @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session) */ public Object doInHibernate(Session session) throws HibernateException, SQLException { params.clear(); Query query = session.createQuery(queryString()); Iterator<Map.Entry<String, Object>> pIt = params.entrySet().iterator(); while (pIt.hasNext()) { Map.Entry<String, Object> entry = pIt.next(); applyNamedParameterToQuery(query, entry.getKey(), entry.getValue()); } if (paginary) { List total = query.list(); int totalRows = total.size(); paginate.setTotalRow(totalRows); query.setFirstResult(paginate.getStartIndex()); query.setMaxResults(paginate.getPageLine()); } List result = query.list(); return result; } /** * 设置Query接口命名参数 * * @param name * @param value */ protected void setParam(String name, Object value) { this.params.put(name, value); }}/** * 功能概述:<br> * 机柜统计查询类 * * 以下是查询类,具体查询数据时 * *///public class CabinetStatisticSpec extends AbstQueryStringSpec { /** 机房ID */ private Integer compLocaId; @Override public String queryString() { // hql 查询 StringBuffer hql = new StringBuffer( "select cl.name, " + "sum(case when nc.useHigh=null or nc.useHigh=0 then 1 else 0 end) as unusedCabinet, " + "sum(case when nc.useHigh>0 and nc.useHigh<nc.height then 1 else 0 end) as nofullCabinet, " + "sum(case when nc.useHigh>=nc.height then 1 else 0 end) as fullCabinet, " + "count(*) as totalCabinet " + "FROM NetworkCabinets nc,ComputerLocation cl " + "WHERE nc.compLocaId=cl.id "); if (QuerySpecUtil.valid(compLocaId)) { hql.append(" AND nc.compLocaId=:compLocaId "); this.setParam("compLocaId", compLocaId); } hql.append(" group by cl.name "); return hql.toString(); @Override protected void reset() { compLocaId = null; } public Integer getCompLocaId() { return compLocaId; } public void setCompLocaId(Integer compLocaId) { this.compLocaId = compLocaId; }}spec在struts2 action中作为属性,调用service时作为参数,service中直接用DAO查询,参数就是从action中传过来的spec我感觉这个设计还是很好的,遂给出部分代码。希望对大家有一点参考作用