论坛首页 Java企业应用论坛

求一种合适的设计模式解决这个问题

浏览 9601 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-03-12  
求一种合适的设计模式解决这个问题


      
 public String onDelete(Object obj)
	{
		// TODO Auto-generated method stub
		String result="JOBTITLE_DELETE_SUCC";
		log.info("**********deleting*************");
		try
		{ 
		  Object vo=clientDataMap.get("DELETE_OBJECT");
		 
                   if(!BACKUP.equals("1"))
                   {  
                       SpringDao.delete(vo);
                   }
                   else
                   {  
		     SpringBakDao.delete(vo, new String[]{user,actionType,projectUtils.getVOId(vo)});
	           }
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
			result="JOBTITLE_DELETE_FAIL";
		}
		return result;
	}

	public String onInsert(Object obj)
	{   
		String result=module+"_INSERT_SUCC";;
		try
		{ 
		  Object vo=clientDataMap.get("VO");
		  if(!BACKUP.equals("1"))
                        SpringDao.insert(vo);
		  else
			SpringBakDao.insert(vo, new String[]{"Terry",actionType});
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
			result=module+"_INSERT_FAIL";
		}
		log.info("GeneralPersistBO...INSERT()...result:"+result);
		return result;
	}


这是一个进行持久化事务的类,这里有两个DAO分属于不同类型,SpringDao只往一个数据库中存数据,SpringBakDao会往备份数据库中存数据,BACKUP常量控制是哪种持久化方式,问题是,每次crud操作时,
都对BACKUP判断一次, 实在是有冗余代码,不是一个良好的设计,我想到几个方案:

1 使 SpringDao和SpringBakDao都实现一个IDAO接口,但问题是,这两个DAO的crud方法,都是需传入不同的参数个数的,如果想统一起来,可以写一个Adapter,然后实现所有接口方法,再每个Dao继承这个Adapter并重载相关的方法,但是,由于要传入的参数个数不同, 始终要判断BACKUP的值


2 用proxy或interceptor, 都存在一个难点,不同DAO的相同的crud方法的参数都不一样的,就算同一个DAO类型的crud四个方法的参数个数也不一致,例如
SpringBakDao.delete(vo,new String[]{String id}),SpringBak.insert(vo,new String[]{String id,String newId}); 如果我用proxy模式,岂不是要传入最多的参数个数入这个proxy类里面,才能应付所有情况?

两种方案都不是理想的,所以想听听大家的意见,有什么更好的模式可以解决这个问题.谢谢
   发表时间:2007-03-12  
这种场景比较适合用AOP.
0 请登录后投票
   发表时间:2007-03-12  
AOP和proxy是同样的道理, 不方便的地方,我上面提过了.
0 请登录后投票
   发表时间:2007-03-12  
引用
2 用proxy或interceptor, 都存在一个难点,不同DAO的相同的crud方法的参数都不一样的,就算同一个DAO类型的crud四个方法的参数个数也不一致,例如
SpringBakDao.delete(vo,new String[]{String id}),SpringBak.insert(vo,new String[]{String id,String newId}); 如果我用proxy模式,岂不是要传入最多的参数个数入这个proxy类里面,才能应付所有情况?



诚然,你自己已经知道问题的所在了!这个是个不可调和的问题!

你不封装参数提供统一接口就不能利用Aop去解决问题!

其实这就是个取舍!


不清楚你的这些操作到底有多少,但是理想设计上考虑应该包起来。不过到底有没有这个必要你自己要酌情考虑


但是写Adapter到这个地步是不是太晚了,不能再在Dao上做文章了,只能动Proxy!
0 请登录后投票
   发表时间:2007-03-12  
springdao extends basedao
    onDelete(do your work)
    oninsert(do your work)
    datasource:real system datasource
backdao  extends basedao
    onDelete(do your work)
    oninsert(do your work)
    datasource:baackup system datasource
daoHelper:
    getDao() due to your system;
client:
    daoHelper.getDao.oninsert(...);
   
   
0 请登录后投票
   发表时间:2007-03-12  
两个方法的重复代码结构都一样 如下
if(!BACKUP.equals("1"))   
                  {     
                      SpringDao.delete(vo);   
                  }   
                  else  
                  {     
         SpringBakDao.delete(vo, new String[]{user,actionType,projectUtils.getVOId(vo)});   
           }   

很明显这是一种多态。

解决方法:
interface Dao {
     onDelete(...);
     onInsert(...);
}
SpringDao implements Dao
SpringBakDao implements Dao
在Dao的上层去确定要调用SpringDao 或 SpringBakDao

这个问题是典型的用多态代替状态码的重构
0 请登录后投票
   发表时间:2007-03-12  
多态可以解决它的问题吗?好像只会增加复杂度!

接口不定啊!如果用多态,要写很多child!
0 请登录后投票
   发表时间:2007-03-12  

使用Template Method

java 代码
  1. public String onDelete(Object obj)      
  2. {      
  3.     // TODO Auto-generated method stub      
  4.     String result="JOBTITLE_DELETE_SUCC";      
  5.     log.info("**********deleting*************");      
  6.     try     
  7.     {       
  8.       Object vo=clientDataMap.get("DELETE_OBJECT");      
  9.            
  10.                   if(!BACKUP.equals("1"))      
  11.                   {        
  12.                       delete(vo);      
  13.                   }      
  14.                   else     
  15.                   {        
  16.                   delete(vo, new String[]{user,actionType,projectUtils.getVOId(vo)});      
  17.            }      
  18.     }      
  19.     catch(Exception ex)      
  20.     {      
  21.         ex.printStackTrace();      
  22.         result="JOBTITLE_DELETE_FAIL";      
  23.     }      
  24.     return result;      
  25. }      
  26.   
  27. protected  void delete(Object vo) {}   
  28. protected void delete(Object vo,String[] args){};   
  29.   
  30. public String onInsert(Object obj)      
  31. {         
  32.     String result=module+"_INSERT_SUCC";;      
  33.     try     
  34.     {       
  35.       Object vo=clientDataMap.get("VO");      
  36.       if(!BACKUP.equals("1"))      
  37.                        insert(vo);      
  38.       else     
  39.         insert(vo, new String[]{"Terry",actionType});      
  40.     }      
  41.     catch(Exception ex)      
  42.     {      
  43.         ex.printStackTrace();      
  44.         result=module+"_INSERT_FAIL";      
  45.     }      
  46.     log.info("GeneralPersistBO...INSERT()...result:"+result);      
  47.     return result;      
  48. }     
  49.   
  50. protected  void insert(Object vo) {}   
  51. protected void insert(Object vo,String[] args){};  
0 请登录后投票
   发表时间:2007-03-12  

badqiu 写道:

使用Template Method

java 代码
  1. public String onDelete(Object obj)      
  2. {      
  3.     // TODO Auto-generated method stub      
  4.     String result="JOBTITLE_DELETE_SUCC";      
  5.     log.info("**********deleting*************");      
  6.     try     
  7.     {       
  8.       Object vo=clientDataMap.get("DELETE_OBJECT");      
  9.            
  10.                   if(!BACKUP.equals("1"))      
  11.                   {        
  12.                       delete(vo);      
  13.                   }      
  14.                   else     
  15.                   {        
  16.                   delete(vo, new String[]{user,actionType,projectUtils.getVOId(vo)});      
  17.            }      
  18.     }      
  19.     catch(Exception ex)      
  20.     {      
  21.         ex.printStackTrace();      
  22.         result="JOBTITLE_DELETE_FAIL";      
  23.     }      
  24.     return result;      
  25. }      
  26.   
  27. protected  void delete(Object vo) {}   
  28. protected void delete(Object vo,String[] args){};   
  29.   
  30. public String onInsert(Object obj)      
  31. {         
  32.     String result=module+"_INSERT_SUCC";;      
  33.     try     
  34.     {       
  35.       Object vo=clientDataMap.get("VO");      
  36.       if(!BACKUP.equals("1"))      
  37.                        insert(vo);      
  38.       else     
  39.         insert(vo, new String[]{"Terry",actionType});      
  40.     }      
  41.     catch(Exception ex)      
  42.     {      
  43.         ex.printStackTrace();      
  44.         result=module+"_INSERT_FAIL";      
  45.     }      
  46.     log.info("GeneralPersistBO...INSERT()...result:"+result);      
  47.     return result;      
  48. }     
  49.   
  50. protected  void insert(Object vo) {}   
  51. protected void insert(Object vo,String[] args){};  



模版方法是 不能解决重复代码的 。想象一下 如果有10个onXXX()方法都带有

if(!BACKUP.equals("1"))   

  •                   {     
  •                       SpringDao.delete(vo);   
  •                   }   
  •                   else  
  •                   {     
  •          SpringBakDao.delete(vo, new String[]{user,actionType,projectUtils.getVOId(vo)});   
  • }
  • 是不是很白痴 而且如果需求有改变,需要加一个else if ,难道要修改这10个方法吗?

    0 请登录后投票
       发表时间:2007-03-12  
    Class
    DeleteData // data to del
    BakDeleteData //extends DeleteData to del as bak data
    DataOperator //to operate data fuction/action
    DeleteImpInterface //interface to perform delete action
    DeleteBak //implements DeleteImpInterface to del bakeup database's data
    DeleteNormally //implements DeleteImpInterface to del normal database's data

    Test to test the function;

    public class DeleteData
    {
        protected Object vo;

        public DeleteData(Object obj)
        {
            this.vo = obj;
        }

        public Object getVo()
        {
            return vo;
        }

        public void setVo(Object vo)
        {
            this.vo = vo;
        }
    }

    {
        private String[] extParams;

        public BakDeleteData(Object obj){
            super(obj);
        }

        public void setExtParams(String[] extParams)
        {
            this.extParams = extParams;
        }

        public String[] getExtParams()
        {
            return extParams;
        }
    }


    public class DataOperator
    {
        private static Logger log = Logger.getLogger("data/operator");
        private DeleteImpInterface deletor;

         public DataOperator( )
        {
        }
        public DataOperator(DeleteImpInterface deletor)
        {
            this.deletor = deletor;
        }

        public void setDeletor(DeleteImpInterface deletor)
        {
            this.deletor = deletor;
        }

        public DeleteImpInterface getDeletor()
        {
            return deletor;
        }

        public String onDelete(DeleteData obj)
        {
            // TODO Auto-generated method stub
            String result = "JOBTITLE_DELETE_SUCC";
            log.info("**********deleting*************");
            try {
    //              Object vo=clientDataMap.get("DELETE_OBJECT");
    //                   deldata=new DeleteData(obj);
                deletor.delete(obj);

    //                 SpringBakDao.delete(vo, new String[]{user,actionType,projectUtils.getVOId(vo)});

            }
            catch (Exception ex) {
                ex.printStackTrace();
                result = "JOBTITLE_DELETE_FAIL";
            }
            return result;
        }
    }


    public interface DeleteImpInterface
    {
        public void delete(DeleteData d) throws Exception;
    }


    public class DeleteBak implements DeleteImpInterface
    {
        public void delete(BakDeleteData d)
        {
            SpringDao.delete(d.getVo(), d.getExtParams());//use SpringDao to imp,you must define this first.
        }

    public class DeleteNormally implements DeleteImpInterface
    {
        public void delete(DeleteData d)
        {
            SpringDao.delete(d.getVo());());//use SpringDao to imp,you must define this first.

        }
    }
    }

    public class Test
    {
        public static void main(String[] args)
        {
            //get po
            Object vo1 = new Object();//or get po by vo; use SpringDao.getPo(vo) or someone else;
            Object vo2 = new Object();//or get po by vo; use SpringDao.getPo(vo) or someone else;

            //get deleted data
            DeleteData delData1 = new DeleteData(vo1);
            BakDeleteData delData2 = new BakDeleteData(vo2);
            delData2.setExtParams(new String[]{"sss", "ddddd"});

            DataOperator operator = new DataOperator();

            //del normal database's data
            operator.setDeletor(new DeleteNormally());
            operator.onDelete(delData1);

            //del bakeup database's data
            operator.setDeletor(new DeleteBak());
            operator.onDelete(delData2);
            //http://www.iteye.com/topic/59239
        }
    }


    of course it is not perfect one for our purpose,
    but yoou know ,there is no perfect one but the best! try for it,perhaps it is not very well!just try it.

    firstly I just want to say that don't use too much params to pass to methods,encapsulate the for the best;we can modify them easily when params increased or decreased
    secondly, use strategy or bridge.but you must know that,strategy is not the perfect one.maybe someone else
    thirdly, use polymorphism to avoid if/else, that is an effective way.
    have fun!
    0 请登录后投票
    论坛首页 Java企业应用版

    跳转论坛:
    Global site tag (gtag.js) - Google Analytics