基础架构系列篇-基于C++语言与mvc(支持MVVM)模式框架GUI系统

31 篇文章 1 订阅
4 篇文章 0 订阅

看了下貌似有几年没用过算法与C++了,用不到10个小时写的练习项目

1. 关键词

语言C++ 观察者模式 mvc mvvm 抽象(类) 封装 多态 (虚)基类 虚函数 引用 指针 图像库opencv 多线程等

2. 代码

Common.h

#pragma once

#ifndef COMMON_H
#define COMMON_H

#include <iostream>
using namespace std;

#include<opencv2/opencv.hpp>
using namespace cv;

const int SUCCESS = 0;
const int ERROR = -1;

const int TIME_INTERVAL = 50;

enum copy_state { UNCOPYED = 0, COPYED };    //定义拷贝状态枚举
enum update_state { NOTUPDATE = 0, UPDATE };    //定义更新状态枚举

//工具类
class Common {
public:
	static std::time_t getTimeStamp()  //毫秒数
	{
		std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> tp = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
		auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch());
		std::time_t timestamp = tmp.count();
		//std::time_t timestamp = std::chrono::system_clock::to_time_t(tp);
		return timestamp;
	}
};

#endif // COMMON_H

BaseModel.h

#pragma once

#ifndef BASE_MODEL_H
#define BASE_MODEL_H

//基础模型类
class BaseModel
{
    public:
        virtual void empty() {} // 用于编译
};

#endif // BASE_MODEL_H

BaseView.h

#pragma once

#ifndef BASE_VIEW_H
#define BASE_VIEW_H

#include "BaseModel.h"

//基础视图类
class BaseView
{
    public:
       virtual void init() = 0;
       virtual void update(BaseModel* baseModel) = 0;
};

#endif // BASE_VIEW_H

BaseController.h

#pragma once

#ifndef BASE_CONTROLLER_H
#define BASE_CONTROLLER_H

#include "Common.h"
#include "BaseView.h"
#include "BaseModel.h"
#include "ViewListener.h"
#include "ModelListener.h"

//基础控制器类
class BaseController: public ViewListener, public ModelListener
{
    private:
        list<BaseView*> baseViewList;
        list<BaseModel*> baseModelList;
    public:
        BaseController();
        void init(BaseView* baseView, BaseModel* baseModel);
        void onViewChanged(BaseView* baseView);
        void onModelChanged(BaseModel* baseModel);
        void notifyModel(BaseView* baseView);
        void notifyView(BaseModel* baseModel);
};

#endif // BASE_CONTROLLER_H

BaseController.cpp

#include "BaseController.h"

BaseController::BaseController()
{
    cout<< "创建BaseController" << endl;
}

void BaseController::init(BaseView* baseView, BaseModel* baseModel)
{
    cout << "启动BaseController::init" << endl;
    this->baseViewList.push_back(baseView);
    this->baseModelList.push_back(baseModel);
}

void BaseController::onViewChanged(BaseView* baseView)
{
    //cout << "更新BaseController::onViewChanged" << endl;
    notifyModel(baseView);
}

void BaseController::onModelChanged(BaseModel* baseModel)
{
    //cout << "更新BaseController::onModelChanged" << endl;
    notifyView(baseModel);
}

void BaseController::notifyModel(BaseView* baseView)
{
    cout << "更新BaseController::notifyModel " << endl;
    //list<BaseModel*>::iterator baseModelIterator;
    //for (baseModelIterator = baseModelList.begin(); baseModelIterator != baseModelList.end(); baseModelIterator++)
    //{
    //    (*baseModelIterator)->update(baseView);
    //}
}

void BaseController::notifyView(BaseModel* baseModel)
{
    //cout << "更新BaseController::notifyView " << endl;
    list<BaseView*>::iterator baseViewIterator;
    if(baseViewList.size() > 0)
    for (baseViewIterator = baseViewList.begin(); baseViewIterator != baseViewList.end(); baseViewIterator++)
    {
        (*baseViewIterator)->update(baseModel);
    }

}

ViewListener.h

#pragma once

#ifndef VIEW_LISTENER_H
#define VIEW_LISTENER_H

#include "BaseView.h"

//视图监听器
class ViewListener
{
    public:
        virtual void onViewChanged(BaseView* baseView) = 0;
        virtual void notifyModel(BaseView* baseView) = 0;
};

#endif // VIEW_LISTENER_H

ModelListener.h

#pragma once

#ifndef MODEL_LISTENER_H
#define MODEL_LISTENER_H

#include "BaseModel.h"

//模型监听器
class ModelListener
{
    public:
      virtual void onModelChanged(BaseModel* baseModel) = 0;
      virtual void notifyView(BaseModel* baseModel) = 0;
};

#endif // MODEL_LISTENER_H

MainFactry.h

#pragma once

#ifndef MAIN_FACTORY_H
#define MAIN_FACTORY_H

#include "Common.h"
#include "BaseController.h"
#include "ObjectCheckController.h"

/*
 启动类
*/
class MainFactry
{
    public:
       static void init();
};

#endif // MAIN_FACTORY_H

MainFactry.cpp

#include "MainFactry.h"

//持续优化中
//主函数
int main(const int argc, const char **  argv)
{
    cout<< "启动主线程" << endl;
    cout<< "argc=" << argc << endl;
    if (argc > 0)
    {
        for (int k = 0; k < argc; k++)
        {
            cout << "argv=" << argv[k] << endl;
        }
    }
    MainFactry::init();
    return SUCCESS;
}

void MainFactry::init()
{
    cout<< "启动控制器controller" << endl;
    (new ObjectCheckController())->init();
}

ObjectCheckController.h

#pragma once

#ifndef OBJECT_CHECK_CONTROLLER_H
#define OBJECT_CHECK_CONTROLLER_H

#include "Common.h"
#include "BaseController.h"
#include "FrameView.h"
#include "Thread.h"
#include "CheckHandler.h"
#include "SpeedHandler.h"

//物体检测控制器
class ObjectCheckController:public BaseController
{
    private:
        FrameView* frameView;
        CheckHandler* checkHandler;
        SpeedHandler* speedHandler;
    public:
        ObjectCheckController();
        void init();
        void initDisplay();
        void startThread();
};

#endif // OBJECT_CHECK_CONTROLLER_H

ObjectCheckController.cpp

#include "ObjectCheckController.h"

ObjectCheckController::ObjectCheckController()
{
    cout << "创建控制器ObjectCheckController" << endl;
    frameView = new FrameView();
    this->checkHandler = new CheckHandler();
    speedHandler = new SpeedHandler();
}

void ObjectCheckController::init()
{
    cout<< "启动ObjectCheckController::init()" << endl;
    BaseController::init(frameView,NULL);
    startThread();
    initDisplay();
}

void ObjectCheckController::initDisplay()
{
    cout<< "启动视图ObjectCheckController::initDisplay"  << endl;
    frameView->init();
}

void ObjectCheckController::startThread()
{
    cout << "启动2个线程ObjectCheckController::startThread()" << endl;
    checkHandler->init(this);
    speedHandler->init(this);
}

CheckHandler.h

#pragma once

#ifndef CHECK_HANDLER_H
#define CHECK_HANDLER_H

#include "Common.h"
#include "Thread.h"
#include "FrameModelPkg.h"
#include "ModelListener.h"
#include <core/types_c.h>
#include <core/core_c.h>
#include <imgproc/imgproc_c.h>

extern Mat frameCopy;
extern atomic_int isCopyed;

static FrameModelPkg* frameModelCheck;
static ModelListener* modelListenerCheck;

void runCheck();
Mat convertPic(Mat image);
void checkObject(Mat imageBinary);

//计算矩形线程
class CheckHandler:public Thread
{
    public:
        CheckHandler();
        void init(ModelListener* modelListener);
};

#endif // CHECK_HANDLER_H

CheckHandler.cpp

#include "CheckHandler.h"

CheckHandler::CheckHandler()
{
    cout << "创建Checkhandler" << endl;
	frameModelCheck = new FrameModelPkg();
}

void CheckHandler::init(ModelListener* listener)
{
    cout << "启动Checkhandler::init()" << endl;
    modelListenerCheck = listener;
	thread checkThread(runCheck);
	checkThread.detach();
}

void runCheck()
{
    cout<< "运行Checkhandler:: runCheck()"  << endl;
	for (;;)
	{
		if (isCopyed == UNCOPYED)
		{
		}
		if (isCopyed == COPYED)
		{
			checkObject(convertPic(frameCopy));
			isCopyed = UNCOPYED;
		}
		this_thread::sleep_for(std::chrono::milliseconds(TIME_INTERVAL));
	}
}

Mat convertPic(Mat image) {
	if (image.empty())
	{
		cout << "convertPic image.empty()" << endl;
		return image;
	}
	Mat gray, binary, element;
	cvtColor(image, gray, CV_RGB2GRAY);
	threshold(gray, binary, 210, 255, CV_THRESH_TOZERO_INV);
	return binary;
}

string path = "D:/PROJECT/res/imageBinary.jpg";
void checkObject(Mat imageBinary)
{
	if (imageBinary.empty())
	{
		cout << "checkObject imageBinary.empty()" << endl;
		return ;
	}
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;

	findContours(imageBinary, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
	//cout << "CheckHandler contours.size()=" << contours.size() << endl;
	vector<Pkg> pkgs;
	for (int i = contours.size() - 1; i >= 0; i--)
	{
		if (contourArea(contours[i]) <= 6000)
		{
			continue;
		}
		Rect2d rect = boundingRect(contours[i]);
		Pkg pkg(0,rect.x,rect.y,rect.width,rect.height);
		pkgs.push_back(pkg);
	}
	//imwrite(path, imageBinary);
	frameModelCheck->setPkgs(pkgs);
	modelListenerCheck->onModelChanged(frameModelCheck);
}

SpeedHandler.h

#pragma once

#ifndef SPEED_HANDLER_H
#define SPEED_HANDLER_H

#include "Common.h"
#include "Thread.h"

#include "FrameModelSpeed.h"
#include "ModelListener.h"

const int SPEED_VECTOR_SIZE = 1;

extern Mat frame;

static Mat curFrame;
static Mat preFrame;
static Mat curr64f, prev64f;

static FrameModelSpeed* frameModelSpeed;
static ModelListener* modelListenerSpeed;

void runSpeed();
void calcSpeed();

//计算速度线程
class SpeedHandler:public Thread
{
    public:
        SpeedHandler();
        void init(ModelListener* modelListener);
};

#endif // SPEED_HANDLER_H

SpeedHandler.cpp

#include "SpeedHandler.h"

SpeedHandler::SpeedHandler()
{
    cout << "创建SpeedHandler" << endl;
	frameModelSpeed = new FrameModelSpeed();
}

void SpeedHandler::init(ModelListener* listener)
{
    cout << "启动SpeedHandler:: init()" << endl;
    modelListenerSpeed = listener;
	thread speedThread(runSpeed);
	speedThread.detach();
}

void runSpeed()
{
    cout << "运行SpeedHandler:: runSpeed()" << endl;
	calcSpeed();
}

int64 preTimeStamp = Common::getTimeStamp();
int64 curTimeStamp = Common::getTimeStamp();

vector<double> speedVector;
vector<double>::iterator it;
void calcSpeed() {
	cout<< "calcSpeed" << endl;
	for (;;) {
		if (frame.empty())
		{
			cout << "calcSpeed frame.empty()" << endl;
			std::this_thread::sleep_for(std::chrono::milliseconds(TIME_INTERVAL));
			continue;
		}
		cvtColor(frame.clone(), curFrame, COLOR_RGB2GRAY);
		curTimeStamp = Common::getTimeStamp();
		if (curFrame.empty()) {
			cout << "calcSpeed curFrame.empty()" << endl;
			continue;
		}
		if (preFrame.empty()) {
			preFrame = curFrame.clone();
			preTimeStamp = curTimeStamp;
			std::this_thread::sleep_for(std::chrono::milliseconds(TIME_INTERVAL));
			continue;
		}
		preFrame.convertTo(prev64f, CV_64F);
		curFrame.convertTo(curr64f, CV_64F);
		Point2d shift = phaseCorrelate(prev64f, curr64f);
		//double radius = cv::sqrt(shift.x * shift.x + shift.y * shift.y);
		//cout<< "SpeedHandler::radius=" << radius << endl;
		//cout << "SpeedHandler::curTimeStamp - preTimeStamp=" << curTimeStamp - preTimeStamp << endl;
		//double speed = (radius > 2) ? (shift.x) / (curTimeStamp - preTimeStamp) : 0;
		double speed = (abs(shift.x) > 15) ? (shift.x) / (curTimeStamp - preTimeStamp) : 0;
		//cout << "SpeedHandler::shift.x=" << shift.x << endl;
		preFrame = curFrame.clone();
		preTimeStamp = Common::getTimeStamp();
		if (speedVector.size() >= SPEED_VECTOR_SIZE)
		{
			speedVector.erase(speedVector.begin());
		}
		speedVector.push_back(speed);
		double sumSpeed = 0;
		double avgSpeed = 0;
		for (it = speedVector.begin(); it != speedVector.end(); it++)
		{
			sumSpeed += *it;
		}
		avgSpeed = sumSpeed / (speedVector.size());
		frameModelSpeed->setSpeed(avgSpeed);
		modelListenerSpeed->onModelChanged(frameModelSpeed);
		std::this_thread::sleep_for(std::chrono::milliseconds(TIME_INTERVAL * 5));
	}
}

FrameModelSpeed.h

#pragma once

#ifndef FRAME_MODEL_SPEED_H
#define FRAME_MODEL_SPEED_H

#include "Common.h"
#include "BaseModel.h"

//模型-速度类
class FrameModelSpeed :public BaseModel
{
    private:
        double speed;
    public:
        void setSpeed(double speed);
        double getSpeed();
};

#endif // FRAME_MODEL_SPEED_H

FrameModelSpeed.cpp

#include "FrameModelSpeed.h"

void FrameModelSpeed::setSpeed(double speed)
{
    this->speed = speed;
}

double FrameModelSpeed::getSpeed()
{
    return speed;
}

FrameModelPkg.h

#pragma once

#ifndef FRAME_MODEL_RECT_H
#define FRAME_MODEL_RECT_H

#include "Common.h"
#include "BaseModel.h"
#include "Pkg.h"

//模型-矩形类
class FrameModelPkg :public BaseModel
{
    private:
        vector<Pkg> pkgs;
    public:
        void setPkgs(vector<Pkg> pkgs);
        vector<Pkg> getPkgs();
};

#endif // FRAME_MODEL_RECT_H

FrameModelPkg.cpp

#include "FrameModelPkg.h"

void  FrameModelPkg::setPkgs(vector<Pkg> pkgs)
{
    this->pkgs = pkgs;
}

vector<Pkg>  FrameModelPkg::getPkgs()
{
    return pkgs;
}

FrameView.h

#pragma once

#ifndef FRAME_VIEW_H
#define FRAME_VIEW_H

#include "Common.h"
#include "BaseView.h"
#include "FrameModelPkg.h"
#include "FrameModelSpeed.h"

static mutex mutexPkgs;
//static mutex mutexSpeed;

const int PKGS_VECTOR_SIZE = 2;
static vector<vector<Pkg>> pkgsVector;

//显示视图类
class FrameView : public BaseView
{
    private:
        atomic<double> speed = 0;
        vector<Pkg> pkgs;
    public:
        FrameView();
        void init();
        void update(BaseModel* baseModel);

        void checkVideo(string videoFilePath);
        void display();
        vector<Pkg> checkPkgs();

        void setSpeed(double speed);
        double getSpeed();
        void setPkgs(vector<Pkg> pkgs);
        vector<Pkg> getPkgs();
};

#endif // FRAME_VIEW_H

FrameView.cpp

#include "FrameView.h"

const string WINDOW_NAME = "物体检测图片";

const string& videoFilePath = "";

//存储帧图像
Mat frame;
//图像帧拷贝
Mat frameCopy;

atomic_int isCopyed = UNCOPYED;

FrameView::FrameView()
{
	cout << "创建FrameView" << endl;
}

void FrameView::init()
{
	cout<< "启动FrameView::init()" << endl;
	checkVideo(videoFilePath);
}

void FrameView::setSpeed(double speed)
{
	this->speed = speed;
}

double FrameView::getSpeed() {
	return speed;
}

void FrameView::setPkgs(vector<Pkg> pkgs)
{
	this->pkgs = pkgs;
}

vector<Pkg> FrameView::getPkgs()
{
	return pkgs;
}

void FrameView::update(BaseModel* baseModel)
{
	//cout << "更新FrameView::update" << endl;
	if (baseModel == NULL)
	{
		cout << "baseModel == NULL" << endl;
		return;
	}
	if (dynamic_cast<FrameModelSpeed*>(baseModel))
	{
		double updateSpeed = ((FrameModelSpeed*)baseModel)->getSpeed();
		//cout << "FrameView::updateSpeed=" << updateSpeed << endl;
		if (abs(updateSpeed) < 1)
		{
			if (abs(updateSpeed) <= 0.1)
			{
				//mutexSpeed.lock();
				speed = 0;
				//mutexSpeed.unlock();
				//cout << "FrameView::updateSpeed=" << 0 << endl;
			}
			else {
				//mutexSpeed.lock();
				if (abs(updateSpeed - speed) >= 0.1)
				{
					speed = updateSpeed;
					//cout << "FrameView::updateSpeed=" << updateSpeed << endl;
				}
				//mutexSpeed.unlock();
			}
		}
	}
	if (dynamic_cast<FrameModelPkg*>(baseModel))
	{
		//cout << "FrameView::UpdatePkg" << endl;
		vector<Pkg> updatePkgs = ((FrameModelPkg*)baseModel)->getPkgs();
		if (pkgsVector.size() >= PKGS_VECTOR_SIZE)
		{
			pkgsVector.erase(pkgsVector.begin());
		}
		pkgsVector.push_back(updatePkgs);
		updatePkgs = checkPkgs();
		mutexPkgs.lock();
		setPkgs(updatePkgs);
		mutexPkgs.unlock();
	}
}

string framePath = "D:/PROJECT/res/frame.jpg";
int64 t2 = Common::getTimeStamp();
void  FrameView::checkVideo(string path)
{
	cout << "checkVideo path=" << path << endl;
	VideoCapture capture(videoFilePath, 0);
	if (!capture.isOpened())
	{
		cout << "打开视频异常" << endl;
		system("pause");
	}
	int64 lTimeStamp = 0;
	for (;waitKey(1) != 'q';)
	{
		t2 = Common::getTimeStamp();
		capture >> frame;
		if (!frame.empty()) {
			//采集频率X毫秒帧图像
			if ((isCopyed == UNCOPYED) && ((Common::getTimeStamp() - lTimeStamp) >= (TIME_INTERVAL * 3)))
			{
				frameCopy = frame.clone();
				isCopyed = COPYED;
				lTimeStamp = Common::getTimeStamp();
			}
			display();
			cout << "主线程用时:" << Common::getTimeStamp() - t2 << endl;
		}
		else {
			//停止
			cout<< "视频空" << endl;
			break;
		}
	}
	capture.release();
}

vector<Pkg>::iterator it;
void FrameView::display()
{
	Mat frame1 = frame.clone();
	mutexPkgs.lock();
	if (!pkgs.empty())
	{
		for (it = pkgs.begin();it != pkgs.end();it++)
		{
			Rect rect((*it).x, (*it).y,(*it).width,(*it).height);
			rectangle(frame1, rect, Scalar(0, 0, 255), 2, 1, 0);
		}
	}
	mutexPkgs.unlock();
	imshow(WINDOW_NAME, frame1);
}

// 计算更新
vector<Pkg> FrameView::checkPkgs()
{
	vector<Pkg> pkgTemp = pkgs;
	if (pkgsVector.size() == PKGS_VECTOR_SIZE)
	{
		vector<Pkg> pkg0 = pkgsVector[0];
		vector<Pkg> pkg1 = pkgsVector[1];
		//vector<Pkg>::iterator iterator0;
		//vector<Pkg>::iterator iterator1;
		if ((pkg0.size() == pkg1.size())&&(pkg0.size() == pkgTemp.size()))
		{
			//cout << "pkg0.size()=" << pkg0.size() << endl;
			//cout << "pkg1.size()=" << pkg1.size() << endl;
			//cout << "pkgTemp.size()=" << pkgTemp.size() << endl;
			for (int k = pkg0.size() -1;k >= 0; k--)
			{
				if ((k == 0) || (k == (pkg0.size() - 1)))
				{
					Rect rect0(pkg0[k].x, pkg0[k].y, pkg0[k].width, pkg0[k].height);
					Rect rect1(pkg1[k].x, pkg1[k].y, pkg1[k].width, pkg1[k].height);
					//double area0 = (rect0 & rect1).area();
					//double area1 = (rect0 | rect1).area();
					//if ((area0 / area1)> 1.1)
					{}
					double area0 = rect0.area();
					double area1 = rect1.area();
					double area = area0 / area1;
					//cout << "rect0.area()=" << area0 << endl;
					//cout << "rect1.area()=" << area1 << endl;
					//cout << "area0/area1=" << area << endl;
					if ((area < 0.95) || (area > 1.06))
					{
						//cout << "checkPkgs update" << endl;
						pkgTemp[k].x = pkg1[k].x; //(pkgTemp[k].x - pkg1[k].x) < 5? pkgTemp[k].x: pkg1[k].x;
						pkgTemp[k].y = pkg1[k].y; //(pkgTemp[k].y - pkg1[k].y) < 2 ? pkgTemp[k].y : pkg1[k].y;
						pkgTemp[k].width = pkg1[k].width; //(pkgTemp[k].width - pkg1[k].width) < 5 ? pkgTemp[k].width : pkg1[k].width;
						pkgTemp[k].height = pkg1[k].height; //(pkgTemp[k].height - pkg1[k].height) < 2 ? pkgTemp[k].height : pkg1[k].height;
					}
					else
					{
						//cout << "checkPkgs movex speed=" << speed << endl;
						//mutexSpeed.lock();
						double movex = speed * 65.0;
						//mutexSpeed.unlock();
						//cout<< "movex=" << movex << endl;
						pkgTemp[k].x += movex;
					}
				}
			}
		}
		else {
			return pkg1;
		}
	}
	return pkgTemp;
}

Pkg.h

#pragma once

#ifndef PKG_H
#define PKG_H

#include "Common.h"

class Pkg
{
    public:
        long number;
        double x;
        double y;
        double width;
        double height;
        int update;

        Pkg(long number,double x, double y, double width, double height, int update = NOTUPDATE);
};

#endif // PKG_H

Pkg.cpp

#include "Pkg.h"

Pkg::Pkg(long number,double x, double y, double width, double height, int update)
{
    this->number = number;
    this->x = x;
    this->y = y;
    this->width = width;
    this->height = height;
    this->update = update;
}

Thread.h

#pragma once

#ifndef THREAD_H
#define THREAD_H

#include "Common.h"
#include <thread>

//基础线程类
class Thread
{
    public:
        virtual void run() {};
};

#endif // THREAD_H

3. 待优化

架构设计(已更新部分)
增加namespace
基本类的函数(构造 拷贝构造 析构等)
资源占用 (已更新部分)
多线程执行(已更新部分)
模板方式封装
效率等(已更新部分)

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
MVCMVPMVVM是常用的软件设计模式,用于分离应用程序的不同组件,提高代码的可维护性和可重用性。以下是它们的概念和区别: 1. MVC模式(模型-视图-控制器):MVC模式是最古老也是最常用的设计模式之一。它将应用程序分为三个组件:模型、视图和控制器。模型负责处理数据和业务规则,视图负责展示数据给用户,控制器负责处理用户输入并更新模型和视图。MVC模式通过分离关注点,使得修改一个组件对其他组件没有依赖,增强了代码的可维护性。 2. MVP模式(模型-视图-展示器):MVP模式是基于MVC模式的演化,主要用于桌面和移动应用程序的开发。它与MVC的不同之处在于,视图和控制器被合并成一个展示器,展示器负责处理用户输入、更新模型并更新视图。MVP模式通过与视图分离,使得视图的变化不会影响展示器的逻辑。这样,在测试时可以更轻松地独立对展示器进行单元测试。 3. MVVM模式(模型-视图-视图模型):MVVM模式是一种用于构建用户界面的设计模式。它将视图的状态和行为抽象成一个视图模型,视图模型负责处理用户输入、保存视图状态、与模型进行交互,并通过数据绑定将数据自动更新到视图上。MVVM模式通过数据绑定机制,使得视图和模型之间的通信变得更简单,提高了可维护性和可重用性。它常用于Web前端开发和桌面应用程序的现代界面开发。 总结来说,MVCMVPMVVM是三种常见的软件设计模式MVC模式是最早的一种,将应用程序分为模型、视图和控制器,用于分离关注点。MVP模式是基于MVC模式的演化,通过将视图和控制器合并成一个展示器,便于测试和维护。MVVM模式是用于构建用户界面的设计模式,通过视图模型和数据绑定机制,实现了视图与模型之间的解耦。每种模式都有自己的特点和适用场景,根据具体需求选择合适的模式可以提高开发效率和代码质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值