论坛首页 入门技术论坛

模式新手,向高手请教。策略模式这样用对吗?

浏览 6194 次
该帖已经被评为新手帖
作者 正文
   发表时间:2007-05-07  
我实在是花了很大决心打算写此文请教各位高手。因为发现这里高手实在多,帖子质量实在高,我还是刚工作的菜鸟,刚学点模式想在项目里试试,请各位帮忙看看,给点意见,我一定虚心接受。

首先这是一个对帐功能,就是从数据库A得到表1的交易,去和数据库B中表2的交易去匹配,如果没什么问题就pass,一旦有不和谐的地方就作为异常交易显示出来。以下是活动图:

思路大致这样,先得到交易的状态(确认成功,确认失败,已撤销,未确认),根据不同状态去选择不同策略(我当时就这么想的,后来多少感觉有点问题,也许这个根本不是策略模式,唉,就请大家看看)

[img]http://jorwen-fang.iteye.com/upload/picture/pic/3230/bdf25f35-a14f-4a21-8351-e5f6c9f8fe2d.jpg [/img]

1. action部分代码
        List<RequestTrade> exceptionTradeList = new ArrayList();
        try
        {
            CheckTradeService service = CheckTradeService.getInstance();
            List<RequestTrade> trades = service.findAllTradeByDate(((CheckTradeForm )form).getWorkDate());
            for( RequestTrade trade:trades )
            {
                RequestTrade afterCheckTrade = trade.check();
                if(afterCheckTrade.isException())
                {
                    exceptionTradeList.add( trade );
                }
            }
        }
        catch( Exception e )
        {
            e.printStackTrace();
        }

        //........




2.RequestTrade.java 就是表1的javabean而且还是策略类的Context,身兼2职
public class RequestTrade
{
    private Strategy strategy;

    private String fundAccNo;
    private String tradeAccNo; 
    private String requestNo;
    private String voucherNo; 
    private String requestDate; 
    private String requestTime; 
    private String businFlag;  
    private String fundCode; 
    private Long   balance;  
    private String state;   
    private String confirmFlag; 
    private String moneyType;  
    private String originNo;   
    private String exceptionReason; 
    
    
    public RequestTrade check()
    {
        return strategy.check( this );
    }

    //如果exceptionReason最后没有,说明正常,否则就是异常,这里我偷懒了,就这样设计了
    public boolean isException()
    {
        return getExceptionReason() != null && !getExceptionReason().equals("");
    }

 
    public void setConfirmFlag( String confirmFlag )
    {
        this.confirmFlag = confirmFlag;
        initStrategy();
    }

    //其他set,get
    

    //此时根据不同confirmFlag选择不同策略
    private void initStrategy()
    {
        if ( confirmFlag.equals( "0" ) )
        {
            strategy = new StrategyConfirmFailure();
        }
        else if ( confirmFlag.equals( "1" ) )
        {
            strategy = new StrategyConfirmSuccess();
        }
        else if ( confirmFlag.equals( "4" ) )
        {
            strategy = new StrategyAlreadyRepeal();
        }
        else if ( confirmFlag.equals( "9" ) )
        {
            strategy = new StrategyUnconfirm();
        }
    }
}


3.策略类父类
public abstract class Strategy
{
    protected RequestTrade trade;//表1的javabean
    protected Statement stmt;//表2的javabean,由于只有属性和set,get就省略显示此类
    protected CheckTradeService service = CheckTradeService.getInstance();

    //流程,由于4种策略都要有findTrade()和checkMoney(),之后才是各自不同的逻辑
    public final RequestTrade check(RequestTrade trade)
    {
        this.trade = trade;
        try
        {
            findTrade();
            if(stmt != null)
            {
                 checkMoney();
                 otherOperate();
            }
        }
        catch( NoSuchTradeException e )
        {
            trade.setExceptionReason( "找不到该交易" );
        }
        catch( MoneyIsNotMatchException e )
        {
            trade.setExceptionReason( "金额不匹配" );
        }
        catch( UnsuccessfulTradeException e )
        {
            trade.setExceptionReason( "状态不匹配,为失败" );
        }
        catch( SuccessfulTradeException e )
        {
            trade.setExceptionReason( "状态不匹配,为成功" );
        }
        return this.trade;
    }

    final void checkMoney() throws CheckTradeException
    {
        if(stmt.getTradeMoney() != trade.getBalance())
            throw new MoneyIsNotMatchException();
    }


    //这里是这个意思.有些状态从表2中找不到交易是允许的,有些找不到是异常交易
    protected final void findStmt(boolean ifNotFindIsException) throws CheckTradeException
    {
        Statement tmp = service.findStmt( trade.getRequestNo() );
        if(ifNotFindIsException)
        {
            if(tmp == null) throw new NoSuchTradeException();
            else this.stmt = tmp;
        }
        else
        {
            if(tmp != null) this.stmt = tmp;
        }
    }

    abstract protected void findTrade() throws CheckTradeException;

    abstract protected void otherOperate() throws CheckTradeException;
}


4.策略子类,其他3个也差不多,就省略了
public class StrategyConfirmSuccess extends Strategy
{
    protected void findTrade() throws CheckTradeException
    {
        this.findStmt( true );//表示找不到对应交易作为异常交易
    }

    protected void otherOperate() throws CheckTradeException
    {
        if(!stmt.isSuccessStmt())
        {
            throw new UnsuccessfulTradeException();
        }
    }
}


大致就这样设计的,请大家给予强烈批判,因为我觉得肯定问题很多。
   发表时间:2007-05-08  
我觉得没什么大问题,关键的地方就是几个策略的注入问题。initStrategy不是很理想,不如就setStrategy吧,直接把实现注入.
0 请登录后投票
   发表时间:2007-05-08  
没有对不对,只有合适不合适
 
  
0 请登录后投票
   发表时间:2007-05-08  
State模式更贴切一点
0 请登录后投票
   发表时间:2007-05-08  
个人感觉这样一个策略+模板的设计还是不错的。
状态和策略从类图上看就是差不多的。
区别个人感觉State偏向于静态的状态,而策略是偏向于行为。
我也是新手。。。
0 请登录后投票
   发表时间:2007-05-08  
ohlala 写道
State模式更贴切一点

这位说的不错,不过state和strategy本来就是一种模式,只是目的不同才称做两种模式。
0 请登录后投票
   发表时间:2007-05-08  
感谢各位指点,今天还看到设计模式专区里的文章。说没必要刻意使用模式,代码些多了,有经验了,勤于思考者写出来的代码已经潜意识在使用模式,甚至自己也不知道是哪一招。

明白了,我把模式看得太神圣了
0 请登录后投票
   发表时间:2007-05-08  
只要代码没味那就是好代码
如果代码有味再好的模式也不好
0 请登录后投票
   发表时间:2007-05-26  
把所有的变化的抽象都取出来,这取一个,那取一个,仔细分析下,咦,这不就是xx模式+yy模式吗??
自己都不知道自己到底是用了什么了
0 请登录后投票
   发表时间:2007-05-26  
# //此时根据不同confirmFlag选择不同策略 
#     private void initStrategy() 
#     { 
#         if ( confirmFlag.equals( "0" ) ) 
#         { 
#             strategy = new StrategyConfirmFailure(); 
#         } 
#         else if ( confirmFlag.equals( "1" ) ) 
#         { 
#             strategy = new StrategyConfirmSuccess(); 
#         } 
#         else if ( confirmFlag.equals( "4" ) ) 
#         { 
#             strategy = new StrategyAlreadyRepeal(); 
#         } 
#         else if ( confirmFlag.equals( "9" ) ) 
#         { 
#             strategy = new StrategyUnconfirm(); 
#         } 
#     } 

这个方法的代码好像有点多余,直接用set动态注入策略的实现应该更好点。 
0 请登录后投票
论坛首页 入门技术版

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