zoukankan      html  css  js  c++  java
  • 节拍器???

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

    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 < 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());
    } 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;
    }
    }


    观察者

    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

  • 相关阅读:
    b_lg_选学霸(并查集+01背包)
    b_lq_小明的魔法(反向思维)
    多测师课堂019_第一个月综合面试题(01) _高级讲师肖sir
    多测师课堂017_项目数据 _高级讲师肖sir
    linux whoami 显示当前用户的用户名
    linux shutdown 命令 关机 重启
    linux reboot 重启命令
    linux基础 目录
    linux uname 命令 打印系统信息
    前端 CSS层叠性 CSS选择器优先级
  • 原文地址:https://www.cnblogs.com/ffaiss/p/11653434.html
Copyright © 2011-2022 走看看