天天看點

細說MVC 結構

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 結構

以前一直無法舒坦的了解,MVC模式是怎樣實際應用到一個程式上的。

這兩天因為工作google出一幅圖,然後恍然大悟。

圖1.

細說MVC 結構

問題就出在以前所看過的文章上根本沒有提過browser這層。導緻我無法正确了解view的責任、controller的責任,以及兩者明明是分層的,為什麼卻是循環依賴。

我将browser介入其中,重新思考MVC模式究竟如何部署到程式結構上。

圖2.

細說MVC 結構

計算機前的使用者,隻會和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  這兩個方法沒有最好,隻有根據具體的情況選擇最合适的做法。在程式足夠小的情況下,其實是不需要把子產品劃分得那麼清楚的