... ... String 名稱1; String 名稱2; String 名稱3; if (paramater.equals("actionA")) { 名稱1 = ....; 名稱2 = ....; 名稱3 = ....; } else if (paramater.equals("actionB")) { 名稱1 = ....; 名稱2 = ....; 名稱3 = ....; } else if (paramater.equals("actionC")) { 名稱1 = ....; 名稱2 = ....; 名稱3 = ....; } else if (paramater.equals("actionC")) { 名稱1 = ....; 名稱2 = ....; 名稱3 = ....; } else if .... ... ... ...
看到了很多的 if 與 else
這時會有一個問題,就是當我要寫增加或修改時,必須先找到合適的那一段後,再插入自己的程式碼,可能會有一些不方便的地方,如:
1. 程式太過攏長, 久了會不好維護.
2. 當有順序要對掉時, 顯得很麻煩.
於是再不動架構的情況下,找了些資訊看能不能改寫這段程式:
參考了良葛格的筆記(Design Patter). Chain of Responsibility
先看一下改過的程式長什麼樣子,再來討論這個 Design Patter 的用處。
首先程式碼將每一段if else 切成各個 Class 去實作, 而主程式只是將每個 Class 串接起來即可.
其每一個Class 的內容如下:
MailsMetaChain
public class MailsMetaChain extends MetaChain { public void handleRequest(HttpServletRequest request) { if (getPart(request).equals(PARAM_VALUE_MAILS)) { processMailsMetaInfo(request); } else if (next != null) { next.handleRequest(request); } else { defaultRequest(request); } } private void processMailsMetaInfo(HttpServletRequest request) { String title = new StringBuilder() .append(IhergoProperties.get("label.mail")) .append(" - ") .append(IhergoProperties.get("web.title")).toString(); setMeta(request, title, "", ""); } }
其 extends 的 Class MetaChain
public abstract class MetaChain { private static final String PARAAM_KEY_PART = "part"; private static final String PARAAM_KEY_VIEW = "view"; private static final String PARAAM_KEY_TAB = "tab"; ... 中間省略 protected MetaChain next; public void setNextMetaChain(MetaChain next) { this.next = next; } /** * extends class 必須實做的功能 * * @param request */ protected abstract void handleRequest(HttpServletRequest request); /** * 如果沒有 match 到時, 用 default 的 * * @param request */ protected void defaultRequest(HttpServletRequest request) { StringBuilder title = new StringBuilder(); title.append(IhergoProperties.get("web.title")); title.append(" - "); title.append(IhergoProperties.get("web.categorys")); String keyword = IhergoProperties.get("web.keywords"); String desc = IhergoProperties.get("web.description"); setMeta(request, title.toString(), keyword, desc); } /** * 抓取 part * * @param request * @return */ protected String getPart(HttpServletRequest request) { if (request != null) { return StringUtils.defaultIfEmpty(request.getParameter(PARAAM_KEY_PART), ""); } return ""; } /** * 抓取 view * * @param request * @return */ protected String getView(HttpServletRequest request) { if (request != null) { return StringUtils.defaultIfEmpty(request.getParameter(PARAAM_KEY_VIEW), ""); } return ""; } /** * 抓取 tab * * @param request * @return */ protected String getTab(HttpServletRequest request) { if (request != null) { return StringUtils.defaultIfEmpty(request.getParameter(PARAAM_KEY_TAB), ""); } return ""; } protected void setMeta(HttpServletRequest request, String title, String keyword, String desc) { if (StringUtils.isBlank(title)) { title = new StringBuilder() .append(IhergoProperties.get("web.title")) .append(" - ") .append(IhergoProperties.get("web.categorys")).toString(); } if (StringUtils.isBlank(keyword)) { keyword = IhergoProperties.get("web.keywords"); } if (StringUtils.isBlank(desc)) { desc = IhergoProperties.get("web.description"); } request.setAttribute("titleStr", title); request.setAttribute("keywordsStr", keyword); request.setAttribute("descriptionStr", desc); } ... ... }
這樣看起來就很清楚明了了唷!!
其好處,以後只需找到自己的 Class 去修改就可以囉。
來看看Gof寫的一段話:
在一個介面中希望使用者一定可以得到相關的說明主題,如果子元件有說明的話,就顯示相關說明,否則的話就轉發給包括它的容器元件或父元件,以保證使用者的輔助說明請求一定可以得到回應。
當然這不是一種好的解法,也可以再更精進一點,如把每一個實作的 Class 改成 Singleton 必免 new 出太多的 Class
而如果可以改變架構的話,其實可以在進入action時,去實作 setTitle 這個 method ,在 BaseAction 中 implements ISetTitle 即可。
沒有留言:
張貼留言