模式简介
MVC模式是一种架构模式,它包含三个角色:模型(Model),视图(View)和控制器(Controller)。观察者模式可以用来实现MVC模式,观察者模式中的观察目标就是MVC模式中的模型(Model),而观察者就是MVC中的视图(View),控制器(Controller)充当两者之间的中介者(Mediator)。当模型层的数据发生改变时,视图层将自动改变其显示内容。
模式实现
- Model:这是数据层,绝大多数的数据都存储在这一层中。Model层不知道关于view或者controller的任何事情,只是返回数据或者更新数据。在web应用中,常用于数据库存储数据。
- View:这是视图层,用于向用户显示数据。View本身不显示任何数据,而是controller或者model让view显示数据
- Controller:这是控制层,可以看成是MVC的核心部分。控制器相当于用户和系统之间的一个连接,接受用户的请求,获取用户的输入,是用户控制其他控件的控制器.
在MVC中,Model更新的时候,会以观察者的方式,来通知当前所有的视图;之后视图会根据数据进行相应的显示操作。用户不能通过视图更新数据,只可以通过Controller的方式与Model交互。
代码示例
代码中,Student是元数据,Model存储了一系列的Student的数据。之后通过Controller与Model交互,数据变动时,会立刻通知所有的视图。
#include <iostream>
#include <set>
#include <list>
#include <string>
#include <memory>
#include <cassert>
class Student {
public:
inline void setName(std::string &name) {
m_strName = std::move(name);
}
inline void setId(std::string &id) {
m_strId = std::move(id);
}
inline void setScore(int socre) {
if (socre < 0) {
return;
}
m_iScore = socre;
}
std::string getName() {
return m_strName;
}
std::string getId() {
return m_strId;
}
int getScore() {
return m_iScore;
}
bool operator<(const Student &student) const {
std::cout << m_strId << ", " << student.m_strId << std::endl;
return m_strId < student.m_strId;
}
private:
std::string m_strName;
std::string m_strId;
int m_iScore;
};
struct cmp {
bool operator()(const std::shared_ptr<Student>& lt, const std::shared_ptr<Student>& rt) const {
return lt->getId() < rt->getId();
}
};
class View {
public:
View(int id = 0): m_iId(id) {}
void update(const std::set<std::shared_ptr<Student>, cmp>& students) {
std::cout << "View " << m_iId << " updates:\n";
for (const auto& student: students) {
std::cout << "Id: " << student->getId()
<< ", Name: " << student->getName()
<< ", Score: " << student->getScore() << std::endl;
}
}
private:
int m_iId;
};
class Model {
public:
void addStudent(std::string &id, std::string &name, int score) {
auto it = std::make_shared<Student>();
it->setId(id);
it->setName(name);
it->setScore(score);
if (m_Students.find(it) == m_Students.end()) {
m_Students.insert(it);
}
notify();
}
void removeStudent(std::string& id) {
auto student = std::make_shared<Student>();
student->setId(id);
m_Students.erase(student);
std::cout << "Student size: " << m_Students.size() << std::endl;
notify();
}
void addView(std::shared_ptr<View> view) {
m_Views.push_back(std::move(view));
}
void notify() {
for (auto& view: m_Views) {
view->update(m_Students); // 通知视图做出变化
}
}
private:
std::set<std::shared_ptr<Student>, cmp> m_Students;
std::list<std::shared_ptr<View>> m_Views;
};
class Controller {
public:
Controller(Model& model): m_Model(model) {}
void Insert(std::string &id, std::string &name, int socre) {
m_Model.addStudent(id, name, socre);
}
void Delete(std::string &id) {
m_Model.removeStudent(id);
}
void setModel(Model &model) {
m_Model = model;
}
private:
Model& m_Model;
};
int main() {
Model model;
for (int i = 0; i < 3; ++i) { // 添加三个视图
model.addView(std::make_shared<View>(i + 1));
}
Controller controller(model);
std::string name, id;
std::cout << "----------------Insert Data----------------\n";
id = "001";
name = "Tom";
controller.Insert(id, name, 100);
std::cout << "----------------Insert Data----------------\n";
id = "002";
name = "Sam";
controller.Insert(id, name, 80);
std::cout << "----------------Insert Data----------------\n";
id = "003";
name = "Amy";
controller.Insert(id, name, 90);
std::cout << "----------------Insert Data----------------\n";
id = "004";
name = "Lily";
controller.Insert(id, name, 90);
std::cout << "----------------Delete Data----------------\n";
id = "003";
controller.Delete(id);
return 0;
}
输出结果:
----------------Insert Data----------------
View 1 updates:
Id: 001, Name: Tom, Score: 100
View 2 updates:
Id: 001, Name: Tom, Score: 100
View 3 updates:
Id: 001, Name: Tom, Score: 100
----------------Insert Data----------------
View 1 updates:
Id: 001, Name: Tom, Score: 100
Id: 002, Name: Sam, Score: 80
View 2 updates:
Id: 001, Name: Tom, Score: 100
Id: 002, Name: Sam, Score: 80
View 3 updates:
Id: 001, Name: Tom, Score: 100
Id: 002, Name: Sam, Score: 80
----------------Insert Data----------------
View 1 updates:
Id: 001, Name: Tom, Score: 100
Id: 002, Name: Sam, Score: 80
Id: 003, Name: Amy, Score: 90
View 2 updates:
Id: 001, Name: Tom, Score: 100
Id: 002, Name: Sam, Score: 80
Id: 003, Name: Amy, Score: 90
View 3 updates:
Id: 001, Name: Tom, Score: 100
Id: 002, Name: Sam, Score: 80
Id: 003, Name: Amy, Score: 90
----------------Insert Data----------------
View 1 updates:
Id: 001, Name: Tom, Score: 100
Id: 002, Name: Sam, Score: 80
Id: 003, Name: Amy, Score: 90
Id: 004, Name: Lily, Score: 90
View 2 updates:
Id: 001, Name: Tom, Score: 100
Id: 002, Name: Sam, Score: 80
Id: 003, Name: Amy, Score: 90
Id: 004, Name: Lily, Score: 90
View 3 updates:
Id: 001, Name: Tom, Score: 100
Id: 002, Name: Sam, Score: 80
Id: 003, Name: Amy, Score: 90
Id: 004, Name: Lily, Score: 90
----------------Delete Data----------------
Student size: 3
View 1 updates:
Id: 001, Name: Tom, Score: 100
Id: 002, Name: Sam, Score: 80
Id: 004, Name: Lily, Score: 90
View 2 updates:
Id: 001, Name: Tom, Score: 100
Id: 002, Name: Sam, Score: 80
Id: 004, Name: Lily, Score: 90
View 3 updates:
Id: 001, Name: Tom, Score: 100
Id: 002, Name: Sam, Score: 80
Id: 004, Name: Lily, Score: 90