1. 程式人生 > >Java設計模式(十四):MVC設計模式

Java設計模式(十四):MVC設計模式

1. 應用場景

MVC設計模式廣泛應用於桌面應用程式開發和網頁頁面開發這些與使用者互動的應用場景中。

2.概念

眾所周知MVC不是設計模式,是一個比設計模式更大一點的模式,稱作設計模式不合理,應該說MVC它是一種軟體開發架構模式,它包含了很多的設計模式,最為密切是以下三種:Observer (觀察者模式), Composite(組合模式)和Strategy(策略模式)。所以說MVC模式又稱複合模式。MVC(Model-View-Controller) 模式的基本思想是資料,顯示和處理相分離。模型(Model)負責資料管理,檢視(View)負責資料顯示,控制器(Controller)負責業務邏輯和響應策略。

MVC是一種設計模式,強制地把應用程式的輸入,處理和輸出分開,把應用程式分成三個核心模組:Model,View和Console。

  • View:
    • 檢視是使用者看到並與之互動的介面,檢視向用戶顯示相關的資料,並能接收使用者的輸入資料,但是它不進行任何的業務處理;
    • 檢視可以向模型查詢業務狀態,但不能改變模型;
    • 檢視還能接收模型發出的資料更新事件,從而對使用者介面進行同步更新。
  • Model:
    • 模型是應用程式的主體部分,表示業務資料和業務邏輯。一個模型能為多個View提供資料,由於同一個模型可以被多個檢視重用,所以提高了應用的可重用性。
  • Controller:
    • 控制器接收使用者的輸入並呼叫模型和檢視去完成使用者請求,當Web使用者單擊頁面中的提交按鈕來發送html表單時,控制器接收請求並呼叫相應模型元件去處理請求,然後呼叫相應的檢視來顯示模型返回的資料。

在這裡插入圖片描述

3. Class Digram

3.1 Model (模型端)

Mod封裝的是資料來源和所有基於對這些資料的操作。在一個元件中,Model往往表示元件的狀態和操作這些狀態的方法,往往是一系列的公開方法。通過這些公開方法,便可以取得模型端的所有功能。

在這些公開方法中,有些是取值方法,讓系統其他部分可以得到模型端的內部狀態引數,其他的改值方法則允許外部修改模型端的內部狀態。模型端還必須有方法登記檢視,以便在模型端的內部狀態發生變化時,可以通知檢視端。我們可以自己定義一個Subject介面來提供登記和通知檢視所需的介面或者繼承 Java.util.Observable類,讓父類完成這件事。

3.2 多個 View( 檢視端 )

View封裝的是對資料來源Model的一種顯示。一個模型可以由多個檢視,並且可以在需要的時候動態地登記上所需的檢視。而一個檢視理論上也可以同不同的模型關聯起來。

在前言裡提到了,MVC模式用到了合成模式,這是因為在檢視端裡,檢視可以巢狀,比如說在一個JFrame元件裡面,可以有選單元件,很多按鈕元件等。

3.3 多個 Controller( 控制器端 )

封裝的是外界作用於模型的操作。通常,這些操作會轉發到模型上,並呼叫模型中相應的一個或者多個方法(這個方法就是前面在介紹模型的時候說的改值方法)。一般Controller在Model和View之間起到了溝通的作用,處理使用者在View上的輸入,並轉發給Model來更改其狀態值。這樣 Model和View兩者之間可以做到鬆散耦合,甚至可以彼此不知道對方,而由Controller連線起這兩個部分。也在前言裡提到,MVC用到了策略模式,這是因為View用一個特定的Controller的例項來實現一個特定的響應策略,更換不同的Controller,可以改變View對使用者輸入的響應。

3.4 MVC (Model-View-Controller)

MVC (Model-View-Controller) : 模型利用"觀察者"讓控制器和檢視可以隨最新的狀態改變而更新。另一方面,檢視和控制器則實現了"策略模式"。控制器是檢視的行為; 檢視內部使用"組合模"式來管理顯示元件。

以下的MVC解釋圖很好的標示了這種模式:

  • 模型使用觀察者模式,以便觀察者更新,同時保持兩者之間的解耦。
  • 控制器是檢視的策略,檢視可以使用不同的控制器實現,得到不同的行為。
  • 檢視使用組合模式實現使用者介面,使用者介面通常組合了巢狀的元件,像面板、框架和按鈕。

這些模式攜手合作,把MVC模式的三層解耦,這樣可以保持設計乾淨又有彈性。

4. Implementation

一個DJView 的Java Swing程式

MVC Model 類

public interface BeatModelInterface {
	void initialize();
  
	void on();
  
	void off();
  
    void setBPM(int bpm);
  
	int getBPM();
  
	void registerObserver(BeatObserver o);
  
	void removeObserver(BeatObserver o);
  
	void registerObserver(BPMObserver o);
  
	void removeObserver(BPMObserver o);

	void notifyBPMObservers();

	void notifyBeatObservers();
}

public interface BeatObserver {
	void updateBeat();
}

public interface BPMObserver {
	void updateBPM();
}

public class BeatModel implements BeatModelInterface, MetaEventListener {
	Sequencer sequencer;
	ArrayList<BeatObserver> beatObservers = new ArrayList<BeatObserver>();
	ArrayList<BPMObserver> bpmObservers = new ArrayList<BPMObserver>();
	int bpm = 90;
	Sequence sequence;
	Track track;

	public void initialize() {
		setUpMidi();
		buildTrackAndStart();
	}

	public void on() {
		System.out.println("Starting the sequencer");
		sequencer.start();
		setBPM(90);
	}

	public void off() {
		setBPM(0);
		sequencer.stop();
	}

	public void setBPM(int bpm) {
		this.bpm = bpm;
		sequencer.setTempoInBPM(getBPM());
		notifyBPMObservers();
	}

	public int getBPM() {
		return bpm;
	}

	void beatEvent() {
		notifyBeatObservers();
	}


	public void registerObserver(BeatObserver o) {
		beatObservers.add(o);
	}

	public void notifyBeatObservers() {
		for(int i = 0; i < beatObservers.size(); i++) {
			BeatObserver observer = (BeatObserver)beatObservers.get(i);
			observer.updateBeat();
		}
	}

	public void registerObserver(BPMObserver o) {
		bpmObservers.add(o);
	}

	public void notifyBPMObservers() {
		for(int i = 0; i < bpmObservers.size(); i++) {
			BPMObserver observer = (BPMObserver)bpmObservers.get(i);
			observer.updateBPM();
		}
	}


	public void removeObserver(BeatObserver o) {
		int i = beatObservers.indexOf(o);
		if (i >= 0) {
			beatObservers.remove(i);
		}
	}



	public void removeObserver(BPMObserver o) {
		int i = bpmObservers.indexOf(o);
		if (i >= 0) {
			bpmObservers.remove(i);
		}
	}


	public void meta(MetaMessage message) {
		if (message.getType() == 47) {
			beatEvent();
			sequencer.start();
			setBPM(getBPM());
		}
	}

	public void setUpMidi() {
		try {
			sequencer = MidiSystem.getSequencer();
			sequencer.open();
			sequencer.addMetaEventListener(this);
			sequence = new Sequence(Sequence.PPQ,4);
			track = sequence.createTrack();
			sequencer.setTempoInBPM(getBPM());
			sequencer.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
		} catch(Exception e) {
			e.printStackTrace();
		}
	} 

	public void buildTrackAndStart() {
		int[] trackList = {35, 0, 46, 0};

		sequence.deleteTrack(null);
		track = sequence.createTrack();

		makeTracks(trackList);
		track.add(makeEvent(192,9,1,0,4));      
		try {
			sequencer.setSequence(sequence);                    
		} catch(Exception e) {
			e.printStackTrace();
		}
	} 

	public void makeTracks(int[] list) {        

		for (int i = 0; i < list.length; i++) {
			int key = list[i];

			if (key != 0) {
				track.add(makeEvent(144,9,key, 100, i));
				track.add(makeEvent(128,9,key, 100, i+1));
			}
		}
	}

	public  MidiEvent makeEvent(int comd, int chan, int one, int two, int tick) {
		MidiEvent event = null;
		try {
			ShortMessage a = new ShortMessage();
			a.setMessage(comd, chan, one, two);
			event = new MidiEvent(a, tick);

		} catch(Exception e) {
			e.printStackTrace(); 
		}
		return event;
	}
}

MVC Controller 類
public interface ControllerInterface {
	void start();
	void stop();
	void increaseBPM();
	void decreaseBPM();
 	void setBPM(int bpm);
}

public class BeatController implements ControllerInterface {
	BeatModelInterface model;
	DJView view;
   
	public BeatController(BeatModelInterface model) {
		this.model = model;
		view = new DJView(this, model);
        view.createView();
        view.createControls();
		view.disableStopMenuItem();
		view.enableStartMenuItem();
		model.initialize();
	}
  
	public void start() {
		model.on();
		view.disableStartMenuItem();
		view.enableStopMenuItem();
	}
  
	public void stop() {
		model.off();
		view.disableStopMenuItem();
		view.enableStartMenuItem();
	}
    
	public void increaseBPM() {
        int bpm = model.getBPM();
        model.setBPM(bpm + 1);
	}
    
	public void decreaseBPM() {
        int bpm = model.getBPM();
        model.setBPM(bpm - 1);
  	}
  
 	public void setBPM(int bpm) {
		model.setBPM(bpm);
	}
}

MVC View 類
public class BeatBar extends JProgressBar implements Runnable { 
	private static final long serialVersionUID = 2L;
    JProgressBar progressBar;
	Thread thread;

	public BeatBar() {
		thread = new Thread(this);
		setMaximum(100);
		thread.start();
	}

	public void run() {
		for(;;) {
			int value = getValue();
			value = (int)(value * .75);
			setValue(value);
			repaint();
			try {
				Thread.sleep(50);
			} catch (Exception e) {};
		}
	}
}

public class DJView implements ActionListener, BeatObserver, BPMObserver {
	BeatModelInterface model;
	ControllerInterface controller;
    JFrame viewFrame;
    JPanel viewPanel;
	BeatBar beatBar;
	JLabel bpmOutputLabel;
    JFrame controlFrame;
    JPanel controlPanel;
    JLabel bpmLabel;
    JTextField bpmTextField;
    JButton setBPMButton;
    JButton increaseBPMButton;
    JButton decreaseBPMButton;
    JMenuBar menuBar;
    JMenu menu;
    JMenuItem startMenuItem;
    JMenuItem stopMenuItem;

    public DJView(ControllerInterface controller, BeatModelInterface model) {	
		this.controller = controller;
		this.model = model;
		model.registerObserver((BeatObserver)this);
		model.registerObserver((BPMObserver)this);
    }
    
    public void createView() {
		// Create all Swing components here
        viewPanel = new JPanel(new GridLayout(1, 2));
        viewFrame = new JFrame("View");
        viewFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        viewFrame.setSize(new Dimension(100, 80));
        bpmOutputLabel = new JLabel("offline", SwingConstants.CENTER);
		beatBar = new BeatBar();
		beatBar.setValue(0);
        JPanel bpmPanel = new JPanel(new GridLayout(2, 1));
		bpmPanel.add(beatBar);
        bpmPanel.add(bpmOutputLabel);
        viewPanel.add(bpmPanel);
        viewFrame.getContentPane().add(viewPanel, BorderLayout.CENTER);
        viewFrame.pack();
        viewFrame.setVisible(true);
	}
  
  
    public void createControls() {
		// Create all Swing components here
        JFrame.setDefaultLookAndFeelDecorated(true);
        controlFrame = new JFrame("Control");
        controlFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        controlFrame.setSize(new Dimension(100, 80));

        controlPanel = new JPanel(new GridLayout(1, 2));

        menuBar = new JMenuBar();
        menu = new JMenu("DJ Control");
        startMenuItem = new JMenuItem("Start");
        menu.add(startMenuItem);
        startMenuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                controller.start();
            }
        });
        stopMenuItem = new JMenuItem("Stop");
        menu.add(stopMenuItem); 
        stopMenuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                controller.stop();
            }
        });
        JMenuItem exit = new JMenuItem("Quit");
        exit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                System.exit(0);
            }
        });

        menu.add(exit);
        menuBar.add(menu);
        controlFrame.setJMenuBar(menuBar);

        bpmTextField = new JTextField(2);
        bpmLabel = new JLabel("Enter BPM:", SwingConstants.RIGHT);
        setBPMButton = new JButton("Set");
        setBPMButton.setSize(new Dimension(10,40));
        increaseBPMButton = new JButton(">>");
        decreaseBPMButton = new JButton("<<");
        setBPMButton.addActionListener(this);
        increaseBPMButton.addActionListener(this);
        decreaseBPMButton.addActionListener(this);

        JPanel buttonPanel = new JPanel(new GridLayout(1, 2));

		buttonPanel.
            
           

相關推薦

Java設計模式()MVC設計模式

1. 應用場景 MVC設計模式廣泛應用於桌面應用程式開發和網頁頁面開發這些與使用者互動的應用場景中。 2.概念 眾所周知MVC不是設計模式,是一個比設計模式更大一點的模式,稱作設計模式不合理,應該說MVC它是一種軟體開發架構模式,它包含了很多的設計模式,最為密切是以下三種:Obs

路一步步走>> 設計模式Command-命令

package com.test.DPs.XingWei.Command; /** * 行為型:Command-命令 外觀:作用面為 物件 * * 用途:將一個請求封裝為一個物件,從而使你可用不同的請求對客戶進行引數化; * 將請求排隊或記錄請求日誌,以及支援可撤銷操作。

Java設計模式(二)狀態設計模式

1.應用場景 在軟體開發過程中,應用程式可能會根據不同的情況作出不同的處理。最直接的解決方案是將這些所有可能發生的情況全都考慮到。然後使用if… ellse語句來做狀態判斷來進行不同情況的處理。但是對複雜狀態的判斷就顯得“力不從心了”。隨著增加新的狀態或者修改一個狀體(if else(或

Java設計模式(一)組合設計模式

1. 應用場景 這種組合模式正是應樹形結構而生,所以組合模式的使用場景就是出現樹形結構的地方。比如:檔案目錄顯示,多及目錄呈現等樹形結構資料的操作。 2. 概念 將物件組合成樹形結構來表示“整體/部分”層次關係,允許使用者以相同的方式處理單獨物件和組合物件。 3. Class

設計模式抽象工廠模式

抽象工廠模式(Abstract Factory Pattern)是圍繞一個超級工廠建立其他工廠。該超級工廠又稱為其他工廠的工廠。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。 在抽象工廠模式中,介面是負責建立一個相關物件的工廠,不需要顯式指定它們的類。每

Java核心程式設計Applet與Web

1 Applet基礎 1.1 Applet簡介 Applet是一種將Java程式,通常為UI程式載入進web瀏覽器,在使用者的瀏覽器中執行的一套轉換機制。因而HTML頁面中必須支援相關的標籤,告訴瀏覽器下載哪些類檔案,以及如何在網頁上進行顯示的資訊。如果一切就緒,則由瀏覽器

Java第三天(MVC設計模式

MVC設計模式 JSP的開發模式 三層架構&MVC練習 學生資訊管理系統 資料庫準備 CREATE DATABASE

設計模式二之MVC模式(Java)

這是我看Head first設計模式書籍之後想要總結的知識點,一方面是對自己學習的東西總結和提煉加強自己的理解和記憶,另一方面是給大家簡化這本書,方便大家快速瞭解各種設計模式。 我想提醒大家的是,設計模式只是前人總結的一些經驗套路,實際上還是要在開發專案中慢慢體會,不可成為

《大話設計模式Java程式碼示例()之備忘錄模式

備忘錄模式(Memonto):在不破壞封裝性的前提下,捕獲一個物件的內部狀態,並在該物件之外儲存這個狀態,這樣以後就可將該物件恢復到原先儲存的狀態。 package memento; /** * 備忘錄模式(Memento) * 遊戲角色 */ public

Java設計模式(五)橋接設計模式

1. 應用場景 假如你正在為一個新的人體工學且友好的電視遙控器程式設計。你要使用好的OO技能,讓所有的遙控器都基於相同的抽象,對此抽象又做出不同的實現—每部不同型號的電視機都有自己的遙控器的實現。 2. 概念 使用橋接設計模式,不只改變你的實現,也改變你的抽象。將抽象與實現分離開

Java設計模式()工廠設計模式

1. 工廠設計模式 1.1 應用場景 由於需求的變化,一個類的子類經常面臨著劇烈的變化,但他卻擁有比較穩定的介面。使用一種封裝機制來“隔離這種易變物件的變化”,工廠方法定義一個用於建立物件的介面,讓子類來確定建立哪一個具體類的物件,將物件的例項化延遲。 1.2 概念 定義了一

java常用設計模式建造者模式

規則 擴展 cto 抽象 具體類 代碼量 特定 clas class 1、定義 是一種對象構建的設計模式,它可以將復雜對象的建造過程抽象出來(抽象類別),使這個抽象過程的不同實現方法可以構造出不同表現(屬性)的對象。 產品類:一般是一個較為復雜的對象,也就是說創建對象的過

Java設計模式(二二)原型設計模式

1. 應用場景 如果一個物件的建立總是由幾種固定元件不同方式組合而成; 如果物件之間僅僅例項屬性不同。將不同情況的物件快取起來,直接克隆使用。也許這比採用傳遞引數重新 new 一個物件要來的快一些與工廠模式的區別:原型模式相當於”改進版的工廠模式”:物件實現了Clonnable()介面,

Java程式設計師從笨鳥到菜鳥之(三)大話設計模式(五)建立者模式和原型模式

        建立者模式是建立型模式中最負責的一個設計模式了,建立者負責構建一個物件的各個部分,並且完成組裝的過程.構建模式主要用來針對複雜產品生產,分離部件構建細節,以達到良好的伸縮性。把構造物件例項的邏輯移到了類的外部,在這個類外部定義了這個類的構造邏輯。它把一個複雜物件的構過程從物件的表示中分離

[Java][Web]Request 實現轉發和 MVC 設計模式

寫入 頁面 str quest 表示 請求轉發 但是 write att String data = "aaaaa"; request.setAttribute("data",data); // 將數據存在 request request.getRequestDispat

設計模式橋接模式(Bridge)

ora 它的 pla sin string src ams down ng- 橋接模式: 將抽象部分和它的實現部分相分離開來,以使它們能夠單獨地變化。 UML圖: 主要包含: Abstraction:定義了抽象部分的接口。操作一個實現部分對

文獻綜述基於Oracle11g的超市進銷存管理系統設計與實現

一、基本資訊   標題:基於Oracle11g的超市進銷存管理系統設計與實現   時間:2016   出版源:技術創新   檔案分類:對資料庫的研究 二、研究背景   為超市設計開發的超市管理系統,採用的是 VC+ Oracle模 式的電子管理平臺,研究基於C/S模式的電子資訊管理的實現。 三、具體內容   

路一步步走>> 設計模式Observer-觀察者

package com.test.DPs.XingWei.Observer; import java.util.Enumeration; import java.util.Vector; /** * 行為型:Observer-觀察者 外觀:作用面為 物件 */ interface Ob

路一步步走>> 設計模式Memento-備忘錄

package com.test.DPs.XingWei.Memento; /** * 行為型:Memento-備忘錄 外觀:作用面為 物件 */ class Original{ private String value; public String getValue(){ ret

路一步步走>> 設計模式Mediator-中介者

package com.test.DPs.XingWei.Mediator; /** * 行為型:Mediator-中介者 外觀:作用面為 物件 * * 用途:用一箇中介物件來封裝一系列的物件互動。 * 中介者使個物件不需要顯示的相互引用,從而使其耦合鬆散,而且可獨立改變它們