MVC是什麼?
<%
String name = request.getParameter("name");
String password = request.getParameter("password");
UserHandler userHandler = new UserHandler();
if(userHandler.authenticate(name, password)) {
%>
<p>恭喜你,登入成功</p>
} else {
<p>對不起,登入失敗</p>
}
%>
public class LoginServlet extends HttpServlet {
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String message = null;
RequestDispatcher dispatcher = req.getRequestDispatcher("/result.jsp");
String name = req.getParameter("name");
String password = req.getParameter("password");
UserHandler userHandler = new UserHandler();
if(userHandler.authenticate(name, password)) {
message = "恭喜你,登入成功";
} else {
message = "對不起,登入失敗";
}
req.setAttribute("message", message);
dispatcher.forward(req, resp);
}
}
<servlet>
<servlet-name>Login</servlet-name>
<servlet-class>
com.demo2do.servlet.LoginServlet
</servlet-class>
</servlet>
<servlet-mapping>
<url-pattern>
/Login
</url-pattern>
</servlet-mapping>

以前一直無法舒坦的了解,MVC模式是怎樣實際應用到一個程式上的。
這兩天因為工作google出一幅圖,然後恍然大悟。
圖1.
問題就出在以前所看過的文章上根本沒有提過browser這層。導緻我無法正确了解view的責任、controller的責任,以及兩者明明是分層的,為什麼卻是循環依賴。
我将browser介入其中,重新思考MVC模式究竟如何部署到程式結構上。
圖2.
計算機前的使用者,隻會和browser打交道,也就是整個應用程式的界面部署,各種視窗,包括菜單、按鈕、子對話框等等。
我把整個界面部署的代碼,全部放置到browser子產品下。此時無需model、view、controller,僅有browser的代碼,我們就可以給使用者顯示這個界面。
接下來我引入model子產品,這個子產品的代碼和視窗無關、和控件無關、和HWND無關。就是一個背景運作的東西,不需要面向任何使用者。
model包含了業務的本質資料結構和邏輯流程。
然後我引入view子產品,view子產品代碼的責任就是,如何利用browser顯示model的内容。
這個責任有兩個潛在意義:
1. browser子產品的代碼不會去通路model子產品的内容,并顯示在browser相應的視窗上。
2. 在沒有controller的情況下——使用者不能操作程式界面上的任何菜單、按鈕,隻能看不能摸,view子產品能夠在browser上給使用者顯示model的内容。
是以,view子產品在MVC模式中所能做的就是:
1. 通路model子產品,擷取内容。
2. 通路browser子產品,修改視窗。
最後引入controller子產品。
使用者在計算機前看着browser,浏覽業務資料,他肯定會做一些操作,比如按下按鈕,選個菜單或者其他什麼的。
使用者修改model子產品的每一個決定性操作,就映射在controller子產品的一個接口上。controller子產品的責任是,代表使用者的每一個動作,并分解為多個view做什麼,model做什麼的調用。這個動作必須有操作model或者view的代碼,不然這個動作放在browser子產品下就可以了。
現在合起來分析個例子,使用者通過browser向model添加一個任務。
按下确定按鈕後,browser讀取其他子視窗的輸入資料,當做參數傳遞給controller子產品對應的調用。
l controller子產品不會主動的從browser中的控件中讀取資料。如果使用者的動作足夠簡單,controller有可能就僅僅作為一個中間層調用model子產品。
controller子產品将使用者的動作分解為一些更細緻的調用:
1. 讓model添加新任務。(不關心model怎麼做)
2. 從model中擷取新任務的資訊。
3. 将新任務的資訊傳遞給view,讓他在browser顯示出來。(不關心view怎麼做)
從controller的動作分解中可以看出:
l 和之前view直接通路model擷取資料不一樣,這裡controller從model擷取資料,并交給view。僅由controller通路model是有好處的,使得view和model沒有了耦合。
l 這裡有一個微妙的循環依賴關系,browser依賴于controller,controller依賴于view,view又依賴于browser。
l 解開這一依賴的方法1,提取一個view interface,讓controller依賴于他,而不是依賴于view。提取controller
interface也是同理。
l 方法2,controller不依賴于view,讓view自己負責根據model的狀态改變顯示,即controller負責修改model,view負責讀取model。
l 不過,view和model之間通過controller傳遞資料是有好處的,除了耦合之外,另一個關鍵的地方是,可以在controller中過濾資料,而不用修改model。
l 這兩個方法沒有最好,隻有根據具體的情況選擇最合适的做法。在程式足夠小的情況下,其實是不需要把子產品劃分得那麼清楚的