热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

节拍器???

要点———————————————————————————————————————————————————MVC是复合模式,结合观察者模式、策略模式和组合模式。模式使用观察者模式,

要点
———————————————————————————————————————————————————

MVC是复合模式,结合观察者模式、策略模式和组合模式。
模式使用观察者模式,以便观察者更新,同时保持两者之间解耦。
控制器是视图的策略,视图可以使用不同的控制器实现,得到不同的行为。
视图使用组合模式实现用户界面,用户界面通常组合了嵌套的组件,像面板、框架和按钮。
这些模式携手合作,把MVC模式的三层解耦,这样可以保持设计干净又有弹性。
适配器模式用来将新的模型适配成已有的视图和控制器。
Model 2是MVC在Web上的应用。
在Model 2中,控制器实现成Servlet,而JSP/HTML实现视图


MVC模式
———————————————————————————————————————————————————

 

 

 

 

 

上面这幅图描述的就是MVC模式,下面根据这幅图对MVC进行一下解释。

1、你是用户—你和视图交互

视图是模型的窗口。当你对视图做一些事事(比方说:按下“播放”按钮),视图就告诉控制器你做了什么。控制器会负责处理。

2、控制器要求模型改变状态。

控制器解读你的动作。如果你按下某个按钮,控制器会理解这个动作的意义,并告知模型如何做出对应的动作。

3.控制器也可能要求视图做改变。

当控制器从视图接收到某一动作,结构可能是它也需要告诉视图改变其结果。比方说,控制器可以将界面上的某些按钮或菜单项变成有效或无效。

4.当模型发生改变时,模型会通知视图。

不管是你做了某些动作(比方说按下按钮)还是内部有了某些改变(比方说播放清单的下一首歌开始)只要当模型内的东西改变时,模型都会通知视图它的状态改变了。

5.视图向模型询问状态。

视图直接从模型取得它显示的状态。比方说,当模型通知视图新歌开始播放,视图向模型询问歌名并显示出来。当控制器请求视图改变时,视图也可能向模型询问某些状态。

 

戴着模式的有色眼镜看MVC

MVC使用哪些模式呢,由哪些模式组成的呢?

使用了:

1.策略模式

   视图和控制器实现了策略模式:视图是一个对象,可以被调整使用不同的策略,而控制提供了策略。视图只关心系统中可视的部分,对与任何界面行为,都委托给控制器处理。使用策略模式也可以让视图和模型之间关系解耦,因为控制器负责和模型交互来传递用户的请求。对与工作是怎么完成的,视图豪不知情。

2.观察者模式

   模型实现了观察者模式,当状态改变时,相关对象将持续更新。使用观察者模式,可以让模型完全独立于视图和控制器。同一个模型可以使用不同的视图,甚至可以同时使用多个视图。

3.组合模式

   显示包括了窗口、面板、按钮、文本标签等。每个显示组件如果不是组合节点(例如窗口),就是叶节点(例如按钮)。当控制器告诉视图更新时,只需告诉视图最顶层的组件即可,组合会处理其余的事。

 

以上就是关于MVC使用各种模式的说明,下面来看一个例子介绍本篇博客。

 

利用MVC控制节拍

BeatModelInterface.java


package combined;

public interface BeatModelInterface {

void initialize(); //在BeatModel被初始化之后,就会调用此方法
void on(); //打开节拍器
void off(); //关闭节拍器
void setBPM(int bpm); //设置bmp值
int getBPM(); //获得当前bmp值
void registerObserver(BeatObserver o);
void removeObserver(BeatObserver o);
void registerObserver(BPMObserver o);
void removeObserver(BPMObserver o);
}

模型
BeatModel.java


package combined;

import java.util.ArrayList;

import javax.sound.midi.MetaEventListener;
import javax.sound.midi.MetaMessage;
import javax.sound.midi.MidiEvent;
import javax.sound.midi.MidiSystem;
import javax.sound.midi.Sequence;
import javax.sound.midi.Sequencer;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.Track;

public class BeatModel implements BeatModelInterface, MetaEventListener {
Sequencer sequencer; //定序器(Sequencer)对象知道如何产生真实的节拍
ArrayList beatObservers = new ArrayList(); //两种观察者(一种观察节拍,一种观察BPM改变)
ArrayList bpmObservers = new ArrayList();
int bpm = 90;
Sequence sequence;
Track track;

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

public void on() {
sequencer.start();
setBPM(90);
}

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

public void setBPM(int bpm) {
this.bpm = bpm; //设置BPM实例变量
sequencer.setTempoInBPM(getBPM()); //要求定序器改变BPM
notifyBPMObservers(); //通知所有的BPM观察者,BPM已经改变
}

public int getBPM() {
return bpm;
}

void beatEvent() {
notifyBeatObservers();
}


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

public void notifyBeatObservers() {
for(int i = 0; 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 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());
} 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 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;
}
}


观察者

BeatObserver.java


package combined;

public interface BeatObserver {
void updateBeat();
}


BPMObserver.java
package combined;

public interface BPMObserver {
void updateBPM();
}

视图
BeatBar.java


package combined;

import javax.swing.JProgressBar;

public class BeatBar extends JProgressBar implements Runnable {
JProgressBar progressBar;
Thread thread;


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


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

}

 

DJView.java

package combined;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.imageio.plugins.bmp.BMPImageWriteParam;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;

/**
* 视图类,它是一个观察者,同时关心实时节拍和BPM的改变
* @author Administrator
*
*/
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.add(decreaseBPMButton);
buttonPanel.add(increaseBPMButton);

JPanel enterPanel = new JPanel(new GridLayout(1, 2));
enterPanel.add(bpmLabel);
enterPanel.add(bpmTextField);
JPanel insideCOntrolPanel= new JPanel(new GridLayout(3, 1));
insideControlPanel.add(enterPanel);
insideControlPanel.add(setBPMButton);
insideControlPanel.add(buttonPanel);
controlPanel.add(insideControlPanel);

bpmLabel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
bpmOutputLabel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));

controlFrame.getRootPane().setDefaultButton(setBPMButton);
controlFrame.getContentPane().add(controlPanel, BorderLayout.CENTER);

controlFrame.pack();
controlFrame.setVisible(true);
}

public void enableStopMenuItem() {
stopMenuItem.setEnabled(true);
}

public void disableStopMenuItem() {
stopMenuItem.setEnabled(false);
}

public void enableStartMenuItem() {
startMenuItem.setEnabled(true);
}

public void disableStartMenuItem() {
startMenuItem.setEnabled(false);
}

public void actionPerformed(ActionEvent event) {
if (event.getSource() == setBPMButton) {
int bpm = Integer.parseInt(bpmTextField.getText());
controller.setBPM(bpm);
} else if (event.getSource() == increaseBPMButton) {
controller.increaseBPM();
} else if (event.getSource() == decreaseBPMButton) {
controller.decreaseBPM();
}
}

public void updateBPM() {
if (model != null) {
int bpm = model.getBPM();
if (bpm == 0) {
if (bpmOutputLabel != null) {
bpmOutputLabel.setText("offline");
}
} else {
if (bpmOutputLabel != null) {
bpmOutputLabel.setText("Current BPM: " + model.getBPM());
}
}
}
}

public void updateBeat() {
if (beatBar != null) {
beatBar.setValue(100);
}
}

}

控制器

package combined;

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


BeatController.java
package combined;
/**
* 控制器的实现
* @author Administrator
*
*/
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.disableStartMenuItem();
model.initialize();
}

@Override
public void start() {
model.on();
view.disableStartMenuItem();
view.enableStopMenuItem();
}

@Override
public void stop() {
model.off();
view.disableStopMenuItem();
view.enableStartMenuItem();
}

@Override
public void increaseBPM() {
int bpm = model.getBPM();
model.setBPM(bpm + 1);
}

@Override
public void decreaseBPM() {
int bpm = model.getBPM();
model.setBPM(bpm - 1);
}

@Override
public void setBPM(int bpm) {
model.setBPM(bpm);
}

}

测试
DJTestDrive.java


package combined;

public class DJTestDrive {

public static void main (String[] args) {
BeatModelInterface model = new BeatModel();
ControllerInterface cOntroller= new BeatController(model);
}
}


效果如下图:

    
————————————————
版权声明:本文为CSDN博主「IT_xiao小巫」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wwj_748/article/details/9747941


推荐阅读
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • LeetCode 102 - 二叉树层次遍历详解
    本文详细解析了LeetCode第102题——二叉树的层次遍历问题,提供了C++语言的实现代码,并对算法的核心思想和具体步骤进行了深入讲解。 ... [详细]
  • 如何高效渲染JSON数据
    本文介绍了在控制器中返回JSON结果的方法,并详细说明了如何利用jQuery处理和展示这些数据,为Web开发提供了实用的技巧。 ... [详细]
  • 深入解析Unity3D游戏开发中的音频播放技术
    在游戏开发中,音频播放是提升玩家沉浸感的关键因素之一。本文将探讨如何在Unity3D中高效地管理和播放不同类型的游戏音频,包括背景音乐和效果音效,并介绍实现这些功能的具体步骤。 ... [详细]
  • 3DSMAX制作超现实的体育馆模型
    这篇教程是向脚本之家的朋友介绍3DSMAX制作超现实的体育馆模型方法,教程制作出来的体育馆模型非常地不错,不过教程有点难度,需要有一定基础的朋友学习,推荐到脚本之家,喜欢的朋友可 ... [详细]
  • 默认情况下,Git 使用 Nano 编辑器进行提交信息的编辑,但如果您更喜欢使用 Vim,可以通过简单的配置更改来实现这一变化。本文将指导您如何通过修改全局配置文件来设置 Vim 作为默认的 Git 提交编辑器。 ... [详细]
  • 本文探讨了使用普通生成函数和指数生成函数解决组合与排列问题的方法,特别是在处理特定路径计数问题时的应用。文章通过详细分析和代码实现,展示了如何高效地计算在给定条件下不相邻相同元素的排列数量。 ... [详细]
  • 探讨如何在映射文件中处理重复的属性字段,以避免数据操作时出现错误。 ... [详细]
  • 网络流24题——试题库问题
    题目描述:假设一个试题库中有n道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取m道题组成试卷。并要求试卷包含指定类型的试题。试设计一个满足要求的组卷算 ... [详细]
  • 本文探讨了程序员这一职业的本质,认为他们是专注于问题解决的专业人士。文章深入分析了他们的日常工作状态、个人品质以及面对挑战时的态度,强调了编程不仅是一项技术活动,更是个人成长和精神修炼的过程。 ... [详细]
  • 本文介绍了SIP(Session Initiation Protocol,会话发起协议)的基本概念、功能、消息格式及其实现机制。SIP是一种在IP网络上用于建立、管理和终止多媒体通信会话的应用层协议。 ... [详细]
  • 二维码的实现与应用
    本文介绍了二维码的基本概念、分类及其优缺点,并详细描述了如何使用Java编程语言结合第三方库(如ZXing和qrcode.jar)来实现二维码的生成与解析。 ... [详细]
  • 本文详细介绍了JQuery Mobile框架中特有的事件和方法,帮助开发者更好地理解和应用这些特性,提升移动Web开发的效率。 ... [详细]
  • 本文详细介绍了C++中的构造函数,包括其定义、特点以及如何通过构造函数进行对象的初始化。此外,还探讨了转换构造函数的概念及其在不同情境下的应用,以及如何避免不必要的隐式类型转换。 ... [详细]
  • 本文详细介绍了iOS应用的生命周期,包括各个状态及其转换过程中的关键方法调用。 ... [详细]
author-avatar
小太郎在路上_439
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有