...
...
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 即可。

沒有留言:
張貼留言