Model-View-Controller

MVC模式是个威力强大的复合模式,是由数个设计模式结合起来的模式;

我们先看一下一个mp3播放器的设计,来由浅至深地了解这个设计模式的精髓所在:

从最直观的地方入手,我们不要先入为主的去使用mvc这个模式,而是尝试用自己最为直观的方式去设计这个应用,那么事情会变成这样:

首先从交互的角度,我们先提出需求:

  • 用户界面上需要显示当前歌曲名
  • 用户可以通过按键直接选择上一首,下一首;
  • 用户可以通过menu按键,显示当前MP3中的所有歌曲列表,然后上下按键选择一首歌曲,并通过ok键播放

好的,其实上述需求,明确了一点,这些需求需要有视图,或者至少需要有View去告诉用户各种状态;ok,那有没有不需要view的需求呢?有,比如,按下风扇能转动,这种需求很简单就不需要view, 但是,这不是重点,重点在于,用户需要对机器当前的状态有个直观的感知,或者反馈,比如风扇上如果我们想要做高端,然后会加个面板,告诉用户当前的风速,室内温度等,最终还是免不了会有view的存在,view的形式可以是多样的,可以是网页的形式,可以是led的形式,可以是数码管的形式,这些只是展示方式的不同,真正的核心在于这些view展示的数据本身,这些才是用户真正care的地方;比如我的歌单里有没有某首歌(模型),比如我播放下一曲的时候,是否能正常切过去(控制器);简单总结就是:用户操作,会作用于控制器,控制器判断用户需要切歌,需要更改当前播放的歌曲索引,然后通知player 播放新的歌曲;模型的改变,会相应地引起视图的改变 ;

那么这里使用了哪些设计模式呢?

这里复习一下观察者模式和策略模式:

观察者模式的好处在于,模型对视图没有依赖,其含义是模型部分无需变更,便可以支持视图的替换,或多个视图去展示同一个模型;

纸上得来终觉浅,我们还是从代码的角度来看一下整个事情的细节吧:

class Mp3Model {
public:
int getSongIdxByString(string song);
string getSoneNameByIdx(int idx);
string getCurrentSong() void setCurrentSong(string song) {
// hw hal to set song file
...
// then notify observers
notifyObserver(); // 通知观察者状态改变
}
// 实际的start/stop
void start();
void stop();
void registerObsever(Observer* observer) // model提供注册观察者方法
{
mObserver = observer;
}
private:
void notifyObserver() {
mObserver->onNotify();
}
Observer* mObserver;
}; class Mp3Controller {
public:
Mp3Controller(Mp3Model* model) { mModel = model; }
void playNext() {
mModel->setCurrentSong(mModel->getSongIdxByString(mModel->getCurrentSong()) + 1);
}
void playPrevious() {
mModel->setCurrentSong(mModel->getSongIdxByString(mModel->getCurrentSong()) - 1);
}
void start() { mModel->start();}
void stop() { mModel->stop(); }
private:
Mp3Model* mModel;
}; class Mp3View : public Observer {
public:
Mp3View() {
mModel = new Mp3Model;
mModel->registerObserver((Oberver*)this);
mController = new Mp3Controller(mModel);
}
void on_click_next() { mController->playNext(); }
void on_click_previous() { mController->playPrevious(); }
void on_click_start() { mContrlloer->start(); }
void on_click_stop() { mController->stop(); }
void onNotify() { //实现model变化时的回调,如改变控件状态等 }
void run();
bool live();
private:
Mp3Controller* mController;
Mp3Model* mModel;
}; int main() {
// 创建view需要controller, mode , 创建controller需要model
Mp3View* mp3_view = new Mp3View;
mp3_view.run();
while(mp3_view.live()) {
sleep(1);
}
return 0;
}

最新文章

  1. 利用html5的localStorage做一个备忘录
  2. SQL Server 维护计划实现数据库备份(Step by Step)
  3. Windows与Linux的双系统的安装顺序及Linux的补救办法
  4. HTTPS-透彻学习汇总
  5. Linux 删除文件后空间不释放磁盘空间
  6. php面试题整理
  7. 决定如何开发你的WordPress主题框架
  8. Fortify对移动应用安全的支持
  9. 关于windows service不能访问网络共享盘(NetWork Drive)的解决方案
  10. 跟我一起学写jQuery插件开发方法(转载)
  11. Hibernate学习(二补充)关系映射----基于外键的双向一对一
  12. 内网IP无法访问
  13. JavaScript中的事件模型
  14. 我眼里K-Means算法
  15. mysql中存储字段类型的查询效率
  16. Windows server 安装 OpenSSH
  17. Spring Caching集成Ehcache
  18. kubernetes 集群机器重启后磁盘盘符变化
  19. .Net 学习过程
  20. Oracle 修改oracle数据库名

热门文章

  1. 权限维持之:DSRM 域控权限维持
  2. PostGIS之空间索引
  3. 爆肝200+小时,总结出的 Creator 3.x 入门修炼指南!全免费
  4. Unity的超大开放世界解决方案
  5. Linux如何查看实时滚动日志
  6. Jmeter 如何把 时间戳 转为 本地时间
  7. 将视图直接转换成表的SQL语句
  8. IntelliJ IDEA运行项目的时候提示 Command line is too long 错误
  9. DRF排序
  10. golang defer关键字