<div class="post_content" id="paragraph"> <p>支付網關中須要接入多個支付渠道,如cybs、fortumo、amx,其中cybs爲信用卡支付,其餘兩個爲運營商支付。</p> <p>無論使用那種支付渠道,支付流程都是相似的。顯而易見能夠使用模板方法。首先定義一個模板類,支付流程中各支付渠道通用的方法放在模板類中,特異於各個支付渠道的方法做爲抽象方法,由子類實現。</p> <p>以下圖所示:</p> <p><a href="http://image.codeweblog.com/upload/b/33/b334bcfda115f0d5.png" class="lightbox"><img src="http://image.codeweblog.com/upload/b/33/b334bcfda115f0d5.png" alt="代碼設計之多渠道支付" title="代碼設計之多渠道支付"></a><br></p> <p>其中AbstractPaymentService爲模板類,其餘三個爲各支付渠道實現子類。</p> <p>模板類--AbstractPaymentService僞代碼以下所示:</p> <pre class="hljs java"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">final</span> Logger logger = LoggerFactory.getLogger(AbstractPaymentService.class);javascript
<span class="hljs-function"><span class="hljs-keyword">public</span> PayResultDTO <span class="hljs-title">pay</span><span class="hljs-params">(PayOrderDTO dto)</span></span>{ logger.info(<span class="hljs-string">"Entering pay, and the dto is {}"</span>, dto); <span class="hljs-comment">//將DTO轉爲Entity(數據庫實體)</span> PayOrder payOrder = convertDTOToEntity(dto); <span class="hljs-comment">//落地支付單</span> insertPayOrder(payOrder); <span class="hljs-comment">//去支付 抽象方法 由各個支付渠道本身去實現</span> <span class="hljs-keyword">return</span> doPay(dto); } <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">abstract</span> PayResultDTO <span class="hljs-title">doPay</span><span class="hljs-params">(PayOrderDTO dto)</span> </span>; <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">insertPayOrder</span><span class="hljs-params">(PayOrder payOrder)</span> </span>{ <span class="hljs-comment">// do something here...</span> } <span class="hljs-function"><span class="hljs-keyword">private</span> PayOrder <span class="hljs-title">convertDTOToEntity</span><span class="hljs-params">(PayOrderDTO dto)</span> </span>{ <span class="hljs-comment">//do something here...</span> <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>; } </pre>php
<p>Cybs支付渠道實現子類–CybsPaymentService僞代碼以下:</p> <pre class="hljs java"><span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">protected</span> PayResultDTO <span class="hljs-title">doPay</span><span class="hljs-params">(PayOrderDTO dto)</span> </span>{ <span class="hljs-comment">//使用cybs 第一次支付須要特殊處理</span> <span class="hljs-keyword">if</span>(dto.isFirstPay()) <span class="hljs-keyword">return</span> doFirstPay(); <span class="hljs-keyword">else</span> <span class="hljs-keyword">return</span> doNormalPay(); } <span class="hljs-function"><span class="hljs-keyword">private</span> PayResultDTO <span class="hljs-title">doNormalPay</span><span class="hljs-params">()</span> </span>{ <span class="hljs-comment">//do smething here...</span> <span class="hljs-keyword">return</span> result; } <span class="hljs-function"><span class="hljs-keyword">private</span> PayResultDTO <span class="hljs-title">doFirstPay</span><span class="hljs-params">()</span> </span>{ <span class="hljs-comment">//do smething here...</span> <span class="hljs-keyword">return</span> result; } </pre> <p>其餘兩個支付渠道實現類相似,只要實現doPay方法便可。好比Amx以HttpClient方式調用Amx Server的Http接口發起支付並同步等待返回。</p> <p>若這時須要接入一個新的支付渠道,如Paypal,只需定義一個PaypalPaymentService繼承模板類–AbstractPaymentService,同時實現doPay方法便可。</p> <p>接着再定義一個支付門面類,方便客戶端(交易系統)調用支付方法,即客戶端無需關心是哪一種支付渠道,只須調用pay方法便可。支付門面代碼以下所示:</p> <pre class="hljs java"><span class="hljs-meta">@Service</span> <span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentFacadeService</span> </span>{ <span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> CybsPaymentService cybsPaymentService; <span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> FortumoPaymentService fortumoPaymentService; <span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> AmxPaymentService amxPaymentService;css
<span class="hljs-function"><span class="hljs-keyword">public</span> PayResultDTO <span class="hljs-title">pay</span><span class="hljs-params">(PayOrderDTO dto)</span> </span>{ String payChannel = dto.getPayChannel(); <span class="hljs-keyword">if</span> (payChannel.equalsIgnoreCase(<span class="hljs-string">"cybs"</span>)) <span class="hljs-keyword">return</span> cybsPaymentService.pay(dto); <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (payChannel.equalsIgnoreCase(<span class="hljs-string">"fortumo"</span>)) <span class="hljs-keyword">return</span> fortumoPaymentService.pay(dto); <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (payChannel.equalsIgnoreCase(<span class="hljs-string">"amx"</span>)) <span class="hljs-keyword">return</span> amxPaymentService.pay(dto); <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>; }
} </pre>java
<p>門面類應該有更優雅的實現方式,即不用在門面類的成員變量中所有羅列出全部的支付渠道的實現類。</p> <p>這時客戶端調用支付方法僞代碼示例爲:</p> <pre class="hljs java"><span class="hljs-meta">@Autowired</span> <span class="hljs-keyword">private</span> PaymentFacadeService paymentServcie;jquery
<span class="hljs-function"><span class="hljs-keyword">public</span> MyResultDTO <span class="hljs-title">pay</span><span class="hljs-params">(...)</span></span>{ <span class="hljs-comment">//構造payOrderDTO</span> PayOrderDTO dto = <span class="hljs-keyword">new</span> PayOrderDTO(); <span class="hljs-comment">//填充屬性</span> <span class="hljs-comment">//...</span> PayResultDTO resultDTO = paymentServcie.pay(dto); <span class="hljs-comment">//do something with resultDTO</span> <span class="hljs-keyword">return</span> myResult; } </pre>web
<p>支付門面設計方案二:</p> <pre class="hljs cs"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">PaymentFacadeService2</span> { <span class="hljs-keyword">private</span> Map<String,AbstractPaymentService> channelServiceMap;spring
<span class="hljs-function"><span class="hljs-keyword">public</span> PayResultDTO <span class="hljs-title">pay</span>(<span class="hljs-params">PayOrderDTO dto</span>) </span>{ String payChannel = dto.getPayChannel(); <span class="hljs-keyword">return</span> channelServiceMap.<span class="hljs-keyword">get</span>(payChannel).pay(dto); } <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setChannelServiceMap</span>(<span class="hljs-params">Map<String, AbstractPaymentService> serviceMap</span>) </span>{ <span class="hljs-keyword">this</span>.channelServiceMap = serviceMap; }
} </pre>數據庫
<p>spring 配置:</p> <pre class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">bean</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"paymentFacadeService2"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"com.tcl.gateway.service.refactoring.PaymentFacadeService2"</span>></span> <span class="hljs-tag"><<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"channelServiceMap"</span>></span> <span class="hljs-tag"><<span class="hljs-name">map</span>></span> <span class="hljs-tag"><<span class="hljs-name">entry</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"cybs"</span>></span> <span class="hljs-tag"><<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"com.tcl.gateway.service.refactoring.CybsPaymentService"</span>></span><span class="hljs-tag"></<span class="hljs-name">bean</span>></span> <span class="hljs-tag"></<span class="hljs-name">entry</span>></span> <span class="hljs-tag"><<span class="hljs-name">entry</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"fortumo"</span>></span> <span class="hljs-tag"><<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"com.tcl.gateway.service.refactoring.FortumoPaymentService"</span>></span><span class="hljs-tag"></<span class="hljs-name">bean</span>></span> <span class="hljs-tag"></<span class="hljs-name">entry</span>></span> <span class="hljs-tag"><<span class="hljs-name">entry</span> <span class="hljs-attr">key</span>=<span class="hljs-string">"amx"</span>></span> <span class="hljs-tag"><<span class="hljs-name">bean</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"com.tcl.gateway.service.refactoring.AmxPaymentService"</span>></span><span class="hljs-tag"></<span class="hljs-name">bean</span>></span> <span class="hljs-tag"></<span class="hljs-name">entry</span>></span> <span class="hljs-tag"></<span class="hljs-name">map</span>></span> <span class="hljs-tag"></<span class="hljs-name">property</span>></span> <span class="hljs-tag"></<span class="hljs-name">bean</span>></span> </pre><!-- lightBox --><script type="text/javascript" src="http://www.codeweblog.com/js/js.php"></script><script type="text/javascript" src="http://www.codeweblog.com/js/jquery/jquery-1.2.6.pack.js"></script><script type="text/javascript" src="http://www.codeweblog.com/js/jquery/jquery.lightbox-0.5.js"></script><link rel="stylesheet" type="text/css" href="http://www.codeweblog.com/css/jquery.lightbox-0.5.css" media="screen"><!-- / lightBox --><script type="text/javascript">$(function() {$("a.lightbox").lightBox();});</script> </div>ide