經典軟體體系結構風格(三)
阿新 • • 發佈:2019-02-16
#模型-檢視-控制器風格常被簡稱為MVC風格
--元件:模型、檢視、控制器
--連線件:顯式呼叫、隱式呼叫、其他機制(例如:Http協議)
#工作機制:
Model:
--模型的職責
1.負責資料存取
2.負責業務邏輯實現
3.負責資料驗證
#模型:模型是應用程式的核心。它封裝核心資料與狀態,對模型的修改將擴散到所有檢視中。所有需要從模型獲取資訊的物件都必須註冊為模型的檢視。
在事件驅動系統,當資訊發生改變,模型通知觀察者(observers) (通常是檢視),從而引起檢視反應。
#View:
檢視的職責:
–獲取使用者輸入
–向controller傳送處理請求
–接收來自Controller的反饋
–將model的處理結果顯示給使用者
一個model可能有多個View
#Controller:
控制器職責:
–接收來自客戶的請求
–呼叫model執行
–呼叫View顯示執行結果
控制器:控制器是提供給使用者進行操作的介面。每個檢視與一個控制器元件相關聯。控制器接收使用者的輸入,通常是滑鼠移動、鍵盤輸入等。輸入事件翻譯成服務請求,送到模型或檢視。使用者只通過控制器與系統互動。
#兩個主要分離:
–模型與介面分離
–控制器與檢視分離
#優點:
–將各方面問題分解開來考慮,簡化了系統設計,保證了系統的可擴充套件性。
–改變介面不影響應用程式的功能核心,使得系統易於演化開發,可維護性好。
–同一資訊可以有不同的展現方式。
–業務邏輯更易測試
# 案例
程式碼:
CarModel.java(模型層)
package com.medel; import java.io.*; import java.net.URL; import java.net.URI; import javax.swing.*; import com.view.View; import java.util.*; public class CarModel{ private String[] carNameList; private URL imgURL; private URL carFileUrl; private ImageIcon imgIcon; private String carSelected; private String bitPrice; static final String CARFILES = "CarFiles/"; static final String CARIMAGES = "CarImages/"; public CarModel(){ carNameList=new String[200]; } public void setCarList(String[] cars){ carNameList = cars; } public String[] getCarList(){ return carNameList; } public void setSelectedCar(String sCar){ carSelected = sCar; } public String getSelectedCar(){ return carSelected; } public void setBitPrice(String bPrice){ bitPrice = ""; bitPrice = bitPrice + bPrice; } public String getBitPrice(){ return bitPrice; } public void setupImageIcon(){ String iconStr = CARIMAGES + carSelected+".jpg"; imgIcon = createImageIcon(iconStr); } public ImageIcon getImageIcon(){ return imgIcon; } public void setCarFileURL(){ try{ String fileURLStr = CARFILES + carSelected+ ".html"; URI uri = (new File(fileURLStr)).toURI(); carFileUrl= uri.toURL(); } catch (IOException e){ e.printStackTrace(); } } public URL getCarFileURL(){ return carFileUrl; } protected ImageIcon createImageIcon(String path){ imgURL = getClass().getResource(path); if (imgURL != null) { return new ImageIcon(imgURL); } else { System.err.println("Couldn't find file: " + path); return null; } } public void tell(View view ){ view.update(); } }
檢視層:
View.java
package com.view;
public interface View {
public abstract void update();
}
CarBitView.java
package com.view;
import java.awt.*;
import javax.swing.*;
import com.medel.CarModel;
public class CarBitView extends JFrame implements View{
private JPanel showPanel;
private JLabel bitOfferedLabel;
private JTextArea bitText;
private CarModel model;
public CarBitView(CarModel cmodel) {
super("Car Bit Info View- Observer 2");
model = cmodel;
bitOfferedLabel = new JLabel("Latest bit offered:");
bitText = new JTextArea(4, 20);
bitText.setFont(new Font("Serif", Font.PLAIN, 14));
bitText.setLineWrap(true);
bitText.setWrapStyleWord(true);
Container contentPane = getContentPane();
contentPane.add(bitOfferedLabel, BorderLayout.NORTH);
contentPane.add(bitText, BorderLayout.CENTER);
setSize(400, 150);
setVisible(true);
}
public void update(){
System.out.println("Car bit has been called.");
String sCar= model.getSelectedCar();
String pr = model.getBitPrice();
bitText.append("\n Bit price for "+ sCar + "="+ pr);
}
}
CarGUIView.java
package com.view;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.net.URL;
import com.medel.CarModel;
public class CarGUIView extends JFrame implements View{
private JEditorPane editorPane;
private JScrollPane imagePane;
private JScrollPane textPane;
private JSplitPane splitPane;
private JLabel imgLabel;
private CarModel model;
public CarGUIView(CarModel cmodel){
super("視窗1--車的資訊");
model = cmodel;
buildUpScrollGUI();
}
private void buildUpScrollGUI(){
imgLabel = new JLabel();
imgLabel.setBackground(Color.green);
imgLabel.setMinimumSize(new Dimension(250, 200));
editorPane = new JEditorPane();
editorPane.setEditable(false);
imagePane = new JScrollPane(imgLabel);
imagePane.getViewport().setBackground(Color.green);
textPane = new JScrollPane(editorPane);
textPane.setMinimumSize(new Dimension(250, 200));
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPane.setLeftComponent(imagePane);
splitPane.setRightComponent(textPane);
Dimension minimumSize = new Dimension(130, 100);
imagePane.setMinimumSize(minimumSize);
textPane.setMinimumSize(new Dimension(100, 100));
splitPane.setDividerLocation(160);
splitPane.setPreferredSize(new Dimension(500, 300));
Container contentPane = getContentPane();
contentPane.add(splitPane);
setSize(400, 150);
setVisible(true);
}
public void update(){
try{
URL url = model.getCarFileURL();
editorPane.setPage(url);
System.out.println("We have been called.");
}
catch (IOException e){
e.printStackTrace();
}
ImageIcon imIcon = model.getImageIcon();
imgLabel.setIcon(imIcon);
imgLabel.validate();
}
}
控制層:
Controller.java
package com.control;
import java.awt.event.*;
import javax.swing.*;
import com.medel.CarModel;
import com.view.CarBitView;
import com.view.CarGUIView;
import java.net.URL;
public class Controller implements ActionListener{
private CarAuctionGUI objCarGui;
private CarModel cm;
private CarGUIView civ;
private CarBitView cb;
private String carPrice;
private String[] carList;
public Controller(CarAuctionGUI objCarGui,CarModel cm,
CarGUIView civ,CarBitView cb){
this.objCarGui = objCarGui;
this.cm=cm;
this.civ=civ;
this.cb=cb;
carList = objCarGui.getCarList();
cm.setCarList(carList);
}
public void actionPerformed(ActionEvent e){
String searchResult = null;
if (e.getActionCommand().equals(CarAuctionGUI.EXIT)){
System.exit(1);
}
if (e.getActionCommand().equals(CarAuctionGUI.SEARCH)){
String selectedCar = objCarGui.getSelectedCar();
cm.setSelectedCar(selectedCar);
cm.setCarFileURL();
cm.setupImageIcon();
cm.tell(civ); //civ.update();
}
if (e.getActionCommand().equals(CarAuctionGUI.BIT)){
carPrice = objCarGui.getBitPrice();
cm.setBitPrice(carPrice);
cm.tell(cb); //cb.update();
}
}
}
CarAuctionGUI.java
package com.control;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.awt.event.*;
import com.medel.CarModel;
import com.view.CarBitView;
import com.view.CarGUIView;
public class CarAuctionGUI extends JPanel {
private JTextField bitInputText;
private JLabel lblCarModel;
private JPanel buttonPanel;
private String[] carList;
private JComboBox cmbCarList;
private static CarModel cm;
private static CarGUIView civ;
private static CarBitView cb;
public static final String SEARCH = "尋找";
public static final String BIT = "確定";
public static final String EXIT = "退出";
public CarAuctionGUI(){
super(new GridLayout(1,0));
setUpGUI();
}
private void setUpGUI(){
cmbCarList = new JComboBox();
String[] cl = getCarList();
setUpCarList(cl);
lblCarModel = new JLabel("二手車種類及年份:");
//Create the open button
JButton srchButton = new JButton(SEARCH);
srchButton.setMnemonic(KeyEvent.VK_S);
JButton exitButton = new JButton(EXIT);
exitButton.setMnemonic(KeyEvent.VK_X);
JButton bitButton = new JButton(BIT);
bitButton.setMnemonic(KeyEvent.VK_X);
bitInputText = new JTextField("請輸入你想要的價格:",12);
buttonPanel = new JPanel();
//****************************************************
GridBagLayout gridbag = new GridBagLayout();
buttonPanel.setLayout(gridbag);
GridBagConstraints gbc = new GridBagConstraints();
buttonPanel.add(lblCarModel);
buttonPanel.add(cmbCarList);
buttonPanel.add(srchButton);
buttonPanel.add(bitButton);
buttonPanel.add(exitButton);
buttonPanel.add(bitInputText);
gbc.insets.top = 5;
gbc.insets.bottom = 5;
gbc.insets.left = 5;
gbc.insets.right = 5;
gbc.anchor = GridBagConstraints.EAST;
gbc.gridx = 0;
gbc.gridy = 0;
gridbag.setConstraints(lblCarModel, gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 1;
gbc.gridy = 0;
gridbag.setConstraints(cmbCarList, gbc);
gbc.anchor = GridBagConstraints.EAST;
gbc.insets.left = 2;
gbc.insets.right = 2;
gbc.insets.top = 25;
gbc.anchor = GridBagConstraints.EAST;
gbc.gridx = 0;
gbc.gridy = 3;
gridbag.setConstraints(srchButton, gbc);
gbc.anchor = GridBagConstraints.WEST;
gbc.gridx = 1;
gbc.gridy = 3;
gridbag.setConstraints(exitButton, gbc);
gbc.gridx = 0;
gbc.gridy = 4;
gridbag.setConstraints(bitButton, gbc);
gbc.gridx = 1;
gbc.gridy = 4;
gridbag.setConstraints(bitInputText, gbc);
Controller objButtonHandler = new Controller(this,cm,civ,cb);
srchButton.addActionListener(objButtonHandler);
exitButton.addActionListener(objButtonHandler);
bitButton.addActionListener(objButtonHandler);
add(buttonPanel);
setSize(new Dimension(800, 450));
setVisible(true);
}
public String getSelectedCar() {
return (String) cmbCarList.getSelectedItem();
}
public String getBitPrice(){
return bitInputText.getText();
}
// get the names of all the .html files in a directory
public String[] getCarList(){
File f = new File("CarFiles");
String [] fileNames = f.list();
for(int i=0; i<fileNames.length; i++ ){
int len = fileNames[i].length();
fileNames[i]=fileNames[i].substring(0,len-5);
}
return fileNames;
}
public void setUpCarList(String[] carList){
for(int k=0; k<carList.length; k++) {
cmbCarList.addItem(carList[k]);
}
}
private static void createAndShowGUI() {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("MVC pattern demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CarAuctionGUI newContentPane = new CarAuctionGUI();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
//Display the window.
frame.pack();
frame.setVisible(true);
}
static public void main(String argv[]) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
cm = new CarModel();
civ= new CarGUIView(cm);
cb = new CarBitView(cm);
createAndShowGUI();
}
});
}
}