查看單個文章
舊 2006-05-30, 09:44 PM   #1
snoopy
註冊會員
 
snoopy 的頭像
榮譽勳章
UID - 33737
在線等級: 級別:49 | 在線時長:2676小時 | 升級還需:24小時級別:49 | 在線時長:2676小時 | 升級還需:24小時級別:49 | 在線時長:2676小時 | 升級還需:24小時級別:49 | 在線時長:2676小時 | 升級還需:24小時
註冊日期: 2003-02-02
VIP期限: 2011-06
住址: 台南共和國
文章: 1831
精華: 0
現金: 12744 金幣
資產: 12834 金幣
預設 使用Java實做MVC架構

http://myweb.hinet.net/home12/snoopy123//mvc.jpg


這是去年的一個作業
在這邊分享
使用Java實做MVC架構
MVC是一種將企業邏輯模式 控制模式 畫面呈現模式分開的一種架構
M -> mdel 企業邏輯模式
V -> view 畫面呈現模式
C -> controller 控制模式

MVC架構有許多好處
試想一個股票系統
有許多種呈現模式
比如說
折線圖 長條圖 圓餅圖等等
這三種view必須同時監視企業邏輯模式(股票漲跌)
如果股價沒有變動 持續監控的資源就白白浪費了
如果改由MVC架構的話
則是由控制模式(各種變因)改變股價
由控制模式控制企業邏輯模式
再由企業邏輯模式通知view
一旦股價變動才更新畫面

第二個好處我舉網站的例子
網頁美工不一定懂程式設計
以往寫網頁時都必須將網頁html與jsp或php程式碼混雜
如果修改網頁往往會不小心修改到企業邏輯模式
我們知道企業邏輯模式是網站中最重要的一部分
弄不好就系統毀了
透過MVC可以控制 企業邏輯與畫面完全分離
以後修改會面就不可能動到企業邏輯模式
反之亦然

程式碼
這是一個股票系統
第一個控制模式我是用一個執行緒加亂數不斷改變股價
第二個控制模式我設計成人為操控 可以加或減50%的股價 (駙馬專用)
而控制觸發的事件由企業邏輯模式處理
再由企業邏輯模式通知呈現
呈現模式我用一般視窗畫面呈現

src
語法:
/*
 * Created on 2005/5/31 
 */


import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.Observable;
import java.util.Observer;

/**
 * Model 企業邏輯模式
 * 
 * @uml.dependency supplier="GraphicView"
 * @uml.dependency supplier="NumberVeiw"
 */

class Model extends Observable {
	private String name;

	private int price = 100;

	public Model(String name) {
		this.name = name;
	}

	public void marketControl() {
		int change;
		Double d = new Double(Math.random() * 41);
		change = d.intValue() % 41 - 20;
		if (price + change <= 300 && price + change >= 0) {
			price += change;
		}
		setChanged();
		notifyObservers(new Integer(price));
	}

	public void peopleIncrement() {
		if (price + 50 <= 300) {
			price += 50;
		}
		setChanged();
		notifyObservers(new Integer(price));
	}

	public void peopleDecrement() {
		if (price - 50 >= 0) {
			price -= 50;
		}
		setChanged();
		notifyObservers(new Integer(price));
	}
}
/** * Controller (市場) 由市場控制 */

class MarketController extends Thread {

	/**
	 * 
	 * @uml.property name="model"
	 * @uml.associationEnd multiplicity="(1 1)"
	 */
	private Model model;


	public MarketController(Model m) {
		model = m;
	}

	public void run() {
		while (true) {
			model.marketControl();
			try {
				sleep(100);
			} catch (Exception e) {
			}
		}
	}
}
/** * Controller (個人) 由個人控制 */

class PeopleController extends JFrame implements ActionListener {

	/**
	 * 
	 * @uml.property name="model"
	 * @uml.associationEnd multiplicity="(1 1)"
	 */
	private Model model;

	/**
	 * 
	 * @uml.property name="incrementBtn"
	 * @uml.associationEnd multiplicity="(1 1)"
	 */
	private JButton incrementBtn;

	/**
	 * 
	 * @uml.property name="decrementBtn"
	 * @uml.associationEnd multiplicity="(1 1)"
	 */
	private JButton decrementBtn;


	public PeopleController(Model m, String frameName) {
		super(frameName);
		model = m;
		setBounds(100, 100, 120, 100);
		setResizable(false);
		getContentPane().setLayout(new FlowLayout());
		incrementBtn = new JButton("增加50%");
		decrementBtn = new JButton("減少50%");
		getContentPane().add(incrementBtn);
		getContentPane().add(decrementBtn);
		incrementBtn.addActionListener(this);
		decrementBtn.addActionListener(this);
		setVisible(true);
		addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
	}

	public void actionPerformed(ActionEvent e) {
		JButton btn = (JButton) e.getSource();
		if (btn == incrementBtn) {
			model.peopleIncrement();
		}
		if (btn == decrementBtn) {
			model.peopleDecrement();
		}
	}
}
/** * View (數字模式) */

class NumberVeiw extends JFrame implements Observer {

	/**
	 * 
	 * @uml.property name="tf"
	 * @uml.associationEnd multiplicity="(1 1)"
	 */
	JTextField tf = new JTextField(5);

	public NumberVeiw(String frameName) {
		super(frameName);
		setResizable(false);
		getContentPane().add(tf);
		setBounds(220, 100, 300, 100);
		setVisible(true);
	}

	public void update(Observable obs, Object arg) {
		tf.setText("即時股價 : " + ((Integer) arg).toString());
	}
}
/** * View (圖形模式) */

class GraphicView extends Frame implements Observer {
	private int x = 0 ;
	private int oldX = 0 ;
	private int oldY = 100 ;

	public GraphicView(String frameName) {
		super(frameName);
		setResizable(false);
		setBounds(100, 200, 420, 320);
		setVisible(true);
	}

	public void update(Observable obs, Object arg) {
		Graphics g = getGraphics();
		paint(g);
		if (x % 420 == 0) {
			x = 0;
			oldX = 0;
			update(g);
		}
		x += 2;
		g.setColor(new Color(109, 207, 246));
		g.drawLine(0, 80, 420, 80);
		g.drawLine(0, 140, 420, 140);
		g.drawLine(0, 200, 420, 200);
		g.drawLine(0, 260, 420, 260);
		Integer integer = (Integer) arg;
		int y = integer.intValue();
		if (y < oldY) {
			g.setColor(new Color(0, 255, 0));
		} else {
			g.setColor(new Color(255, 0, 0));
		}
		g.drawLine(oldX, 320 - oldY, x, 320 - y);
		oldX = x;
		oldY = y;
	}
}
/** * 程式進入點 */

public class Home8 {
	public static void main(String[] args) {
		Model model = new Model("Price of Stock");
		PeopleController peopleCtrl = new PeopleController(model,
		"PeopleController");
		MarketController marketCtrl = new MarketController(model);
		NumberVeiw numView = new NumberVeiw("NumberVeiw");
		GraphicView gView = new GraphicView("GraphicView");

		marketCtrl.start();
		model.addObserver(numView);
		model.addObserver(gView);
	}
}

ok解釋一下程式碼

語法:
class Model extends Observable
類別Model 繼承Observable
Model是可以觀察的
一旦股價改變 就會通知view
通知view的程式碼如下
語法:
setChanged();
notifyObservers(new Integer(price));
股價由市場控制
所以我寫了一個MarketController繼承Thread
由這條執行緒亂數控制股價
語法:
class MarketController extends Thread
股價由人為控制
所以我寫了一個視窗介面
可以由按鈕控制股價 內線交易?
語法:
class PeopleController extends JFrame implements ActionListener
數字呈現模式
顯示當前股價
語法:
class NumberVeiw extends JFrame implements Observer
注意我在視窗裡呈現股價
因此繼承JFrame
JFrame就是一個視窗 類似VB的Form
由於Java是單一繼承 所以無法繼承多個類別
但我們可以透過實做介面(implements interface)
或委託來實現多重繼承
我們實作Observer 介面
因此NumberVeiw可以觀察Model
而我們實作update方法 來將改變的股價呈現出來
語法:
public void update(Observable obs, Object arg) {
   tf.setText("即時股價 : " + ((Integer) arg).toString());
}
圖形呈現模式也差不多

語法:
model.addObserver(numView);
model.addObserver(gView);
view向model註冊
讓view可以觀察該model

此帖於 2006-06-04 03:48 AM 被 snoopy 編輯.
snoopy 目前離線  
送花文章: 623, 收花文章: 392 篇, 收花: 1288 次
回覆時引用此帖
向 snoopy 送花的會員:
rezard (2010-02-24)
感謝您發表一篇好文章