设计模式学习--复合模式(Compound Pattern)

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

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

题外话

不管怎么样,不论是什么样的大小面试,要想不被面试官虐的不要不要的,只有刷爆面试题题做好全面的准备,当然除了这个还需要在平时把自己的基础打扎实,这样不论面试官怎么样一个知识点里往死里凿,你也能应付如流啊

这里我为大家准备了一些我工作以来以及参与过的大大小小的面试收集总结出来的一套进阶学习的视频及面试专题资料包,主要还是希望大家在如今大环境不好的情况下面试能够顺利一点,希望可以帮助到大家~

欢迎评论区讨论。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
;

}

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

题外话

不管怎么样,不论是什么样的大小面试,要想不被面试官虐的不要不要的,只有刷爆面试题题做好全面的准备,当然除了这个还需要在平时把自己的基础打扎实,这样不论面试官怎么样一个知识点里往死里凿,你也能应付如流啊

这里我为大家准备了一些我工作以来以及参与过的大大小小的面试收集总结出来的一套进阶学习的视频及面试专题资料包,主要还是希望大家在如今大环境不好的情况下面试能够顺利一点,希望可以帮助到大家~

[外链图片转存中…(img-woGrNXyL-1715394435436)]

欢迎评论区讨论。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值