1. 程式人生 > >JAVA之MVC框架_個人心得與簡單程式實現

JAVA之MVC框架_個人心得與簡單程式實現

//記錄學習心得   後面有一個簡單實現的小程式

前面有兩篇部落格,分別是這裡,和這裡//還在稽核,超連結沒貼.提到了JAVA設計模式中的單例模式和工廠模式

這裡要說的是MVC框架.來看看MVC框架的定義:

MVC全名是Model View Controller,是模型(model)-檢視(view)-控制器(controller)的縮寫,一種軟體設計典範

繼續看更詳細的解釋:

用一種業務邏輯、資料、介面顯示分離的方法組織程式碼,將業務邏輯聚集到一個部件裡面,在改進和個性化定製介面及使用者互動的同時,不需要重新編寫業務邏輯。MVC被獨特的發展起來用於對映傳統的輸入、處理和輸出功能在一個邏輯的圖形化使用者介面的結構中。

這怎麼很像一種設計的模式阿?這或許是廣義上/籠統可以說是設計的一種模式吧, 但不是"設計模式"

單例/`工廠,是設計模式. 

有書<<設計模式>>裡對框架定義為一組相互協作的類,對於特定的一類軟體,框架構成了一種可重用的設計. (又略不同於設計重用)

設計模式研究是一個設計問題的解決辦法,一種設計的重用,一個模式可以用不同的框架/語言去實現.

框架是一個應用的體系結構;而設計模式是給出某一設計問題的解法.

框架是設計+程式碼的混合體

設計模式與語言無關,是一種知識體.//翻了資料,認識比較淺,姑且用這些比較皮毛的隻言片語來區分兩者

搜尋MVC,肯定會有這樣幾張圖,比較經典的是從

這個部落格裡看到的這個:



尤其第二張圖,文字都很直白.

總而言之,這個模式就是 涇渭分明 地將程式的"輸入"  "處理" " 輸出"給分開,分開的目的是什麼?

在我看來,目的主要也是兩個字: "解耦".

解耦的目的大同小異:

0.比如:清晰的分層有利於各個層次的集中注意力以突破.

1. 有利於管理複雜的程式

2. 對於某一部分的修改能儘可能少地修改其他部分從而加強了擴充套件性和除錯性 等等...

要實現各個部件,比如這裡的 MODEL VIEW CONTROLLER 的分離, 一般是三種構思的組合..

Servlet 互動式地瀏覽 修改資料

JavaBean提供符合一致性設計模式的公共方法將內部域暴露成員屬性  (比如GET SET 體現的思想)

JSP ...鵝表示母雞阿,說是一種動態網頁技術標準

按上面的第一張迴圈圖來看. 他把起點設定在了 即將與 Controller 互動的 使用者裡.

     Controller負責等待使用者輸入  ->  資料丟給Model -> Model 進行業務邏輯判斷+資料庫存取 最後導致-> View Update

這裡我們扣一下三個部分的相關說明:

Model(模型)表示應用程式核心(比如資料庫記錄列表)。

    View(檢視)顯示資料(資料庫記錄)。
    Controller(控制器)處理輸入(寫入資料庫記錄)。

我寫下面這個小程式的時候,就遇到這樣一個問題:

如果這三個程式,完全構成了一個圈,那真的能形成嗎? 

Controller 得到資料,提交給 Model (勢必關係到Model)

Model處理一下資料的業務邏輯,存取一下資料,通知一下檢視更新(勢必關係到View)

View進行下一步讀取資料,資料給到Controller

這樣的依賴關係可以通過 介面回撥 實現

--->那麼比如View是一個互動的視窗介面,負責監聽視窗得到資料,傳遞資料和一個事件檢查器給Controller

---> Controller得到資料和檢查器之後,進行簡單的資料判斷之後將資料和檢查器傳遞給M

--->Model對資料進行業務處理並且通過檢查器通知VIEW更新檢視

接下來我就貼出一個解決判斷奇數偶數的程式,用到的是我這樣理解的MVC模式.

大概長這樣


---------------------------------------------------------------

先說大體構思


貼程式碼:

InputEvent.java

public interface InputEvent{        //資料輸入時觸發 VMC三者相關
    public void inputEvent();
}
UpdateEvent.java
public interface UpdateEvent{       //需更新時觸發 V M相關
    public void updateEvent(String result);
}

InputEventNotifier.java

public class InputEventNotifier{
    private InputEvent iEvent;
    private boolean InputEventHappened;

    public InputEventNotifier(InputEvent iEvent){
        this.iEvent=iEvent;
        InputEventHappened=false;
    }

    public void setInputEventHappened(){
        InputEventHappened=true;
    }
    public void handleInputEvent(){
        if(InputEventHappened){
            iEvent.inputEvent();        //介面回撥
        }
    }
}

UpdateEvent.java

public class UpdateEventNotifier{
    private UpdateEvent uEvent;
    private boolean UpdateEventHappened;
    private String result; 
    
    public UpdateEventNotifier(UpdateEvent uEvent){
        this.uEvent=uEvent;
        UpdateEventHappened=false;
    }

    public void setUpdateEventHappened(){
        UpdateEventHappened=true;
    }
    public void handleUpdateEvent(){
        if(UpdateEventHappened){        //介面回撥
            uEvent.updateEvent(result);
        }
    }
    public void setResult(String result){
        this.result=result;
    }
}

myView.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class myMouseClickedListener extends MouseAdapter{  //滑鼠監聽器點選清空
    public void mouseClicked(MouseEvent e){
        JTextField JTF=(JTextField)e.getSource();
        JTF.setText("");
    }
}

public class myView extends JFrame implements InputEvent,UpdateEvent{
    private myControl myC;                          //Controller成員
    private String strFromUser;                     //來自使用者的資料
    private InputEventNotifier ien;                 //輸入事件通知器
    private UpdateEventNotifier uen;                //更新檢視事件通知器

    private JTextField myJTFInput=new JTextField(20);
    private JLabel myJL=new JLabel(" judgeResult : ");
    private JTextField myJTFOutput=new JTextField(20);

    public myView(){                                
        ien=new InputEventNotifier(this);           
        uen=new UpdateEventNotifier(this);
        myC=new myControl();                        //初始化C,為後面銜接做準備
        myC.setuenFromView(this.uen);               //將 View的更新監聽器 給 C



        myJTFOutput.setEditable(false);             
        myJTFInput.setText("");
        myJTFOutput.setText("");
        myJTFInput.addMouseListener(new myMouseClickedListener());  //新增2種監聽
        myJTFInput.addKeyListener(new KeyAdapter(){
            public void keyPressed(KeyEvent e){
                if(e.getKeyCode()==KeyEvent.VK_ENTER){
                    strFromUser=myJTFInput.getText();
                    
                    ien.setInputEventHappened();
                    ien.handleInputEvent();
                }
            }
        });


        setSize(400,100);
        JPanel myPane=new JPanel(new FlowLayout());


        myPane.add(myJTFInput);
        myPane.add(myJL);
        myPane.add(myJTFOutput);                    //元件加入Panel

        setContentPane(myPane);                     //set Panel
        setVisible(true);                           //可見     
    }

    public void inputEvent(){
        myC.setStrFromView(strFromUser);            //資料給C,並且通知C資料來了
        myC.getien().setInputEventHappened();
        myC.getien().handleInputEvent();
    }
    public void updateEvent(String result){         //根據來自Model的通知結果更新檢視
        if(result=="even"){
            myJTFOutput.setText(" 偶數 ");
        }else if(result=="odd"){
            myJTFOutput.setText(" 奇數 ");
        }else{
            myJTFOutput.setText(" 輸入有誤 ");
        }
    }

    public JTextField getJTFInput(){               //get set 
        return myJTFInput;
    }
    public JTextField getJTFOutput(){               
        return myJTFOutput;
    }
    public String getstrFromUser(){                 
        return strFromUser;
    }
}

myControl.java

public class myControl implements InputEvent{
    private myModel myM;
    private String strFromView;
    private InputEventNotifier ien;
    private UpdateEventNotifier uenFromView;

    public myControl(){
        ien=new InputEventNotifier(this);
        myM=new myModel();
    }
    public void inputEvent(){
        if(isDigit(strFromView)){                   //資料基本判斷
            myM.setisString(true);
            myM.setnumFromController(Integer.parseInt(strFromView));
        }else{
            myM.setisString(false);
        }
        myM.getien().setInputEventHappened();       //判斷 傳達資料並且通知Model有資料來了
        myM.getien().handleInputEvent();
    }


    private boolean isDigit(String strNum){
        return strNum.matches("[0-9]{1,}");
    }
    public void setuenFromView(UpdateEventNotifier uenFromView){
        this.uenFromView=uenFromView;               //來自view的uen給到Model
        myM.setUenFromViewByController(this.uenFromView);
    }
    public void setStrFromView(String s){
        strFromView=s;
    }
    public InputEventNotifier getien(){
        return ien;
    }
}

myModel.java
public class myModel implements InputEvent{
    private InputEventNotifier ien;                         //自身的輸入事件通知器
    private UpdateEventNotifier uenFromViewByController;    //來自view的更新事件通知器
    private dataBean db;                                    //資料bean

    private boolean isEven;
    private boolean isString;
    private String result;

    public myModel(){                       //建構函式
        ien=new InputEventNotifier(this);
        isString=true;
        db=new dataBean();
    }


    public void inputEvent(){               //得到輸入通知後對資料判斷並且通知檢視進行更新

        if(isString==true){
            judgeNum();
            if(isEven==true){
                result="even";
            }else{
                result="odd";
            }
        }else{
            result="wrong";
        }
        uenFromViewByController.setResult(result);
        uenFromViewByController.setUpdateEventHappened();
        uenFromViewByController.handleUpdateEvent();

    }
    private void judgeNum(){                 //數字判斷
        if(db.getDataNum()%2==0){
            isEven=true;
        }else{
            isEven=false;
        }
    }
    public void setUenFromViewByController(UpdateEventNotifier u){  
        uenFromViewByController=u;          //得到來自view的更新事件通知器
    }

    public void setisString(boolean s){     //C判斷完使用者輸入是否為String的結果,以影響更新VIEW的選擇
        isString=s;
    }
    public void setnumFromController(int numFromController){    
        db.setDataNum(numFromController);   //把來自C的數字存入後臺資料中
    }
    public InputEventNotifier getien(){
        return ien;
    }
}

dataBean.java
public class dataBean{
    private int dataNum;

    public void setDataNum(int dataNum){
        this.dataNum=dataNum;
    }
    public int getDataNum(){
        return dataNum;
    }
}

mvcMean.java
public class mvcMain{
    public static void main(String args[]){
        myView my_view=new myView();
    }
}

主要..就是介面回調了..保證MVC構成了一個環

編譯順序:

javac

InputEvent.java

UpdateEvent.java

InputEventNotifier.java

UpdateEventNotifier.java

dataBean.java

myModel.java

myControl.java

myView.java

mvcMain.java

執行:

java mvcMain

結果:

左邊的框輸入數字之後 ENTER 就能看結果



(逃