分析:视觉对象:显示数据(菜单,日期)
模式对象:对数据进行处理
控制端对象:来控制视图和模式(关联模式对象,关联视图对象),通知视图进行数据显示。
具体代码如下:
第一步:先写三个对象的头文件头文件ModelDate.h
#ifndef MODELDATE_H
#define MODELDATE_H
//模式端,对数据进行操纵
class ViewDate;
class ModelDate
{
private:
ViewDate* pview;
private:
int year;
int month;
int mday;
int curweek;//这一年这一月的当前星期
int oneweek;//这一年这一月的1号是星期几
int mdays;//这一月的总天数
void SetWM();//初始化函数
public:
void SetView(ViewDate* pv);
int GetYear() const; //获得年份
int GetMongth() const; //获得月份
int GetMday() const;
int GetCurweek() const;
int GetOneweek() const;
int GetMdays() const;
public:
bool Is_Leap() const;//判断当前的年是否为闰年
int GetYM_Day() const;//根据年和月计算总的天数
int GetWeek(int d = 1) const;//这个月的1号是周几
public:
ModelDate();//构造函数
~ModelDate();//析构函数
void Now();//获得当前现在的日期
void NextYear();//下一年
void PrevYear();//上一年
void NextMonth();//下一个月
void PrevMonth();//上一个月
};
#endif
头文件ViewDate.h
#ifndef VIEWDATE_H
#define VIEWDATE_H
class ModelDate;
class ViewDate
{
private:
public:
ViewDate();
~ViewDate();
int Menum();//显示菜单
void PrintDate(int y, int m, int md, int ow, int mt) const;//打印日期
void Event(ModelDate* pmodel);
};
#endif
头文件controller.h
#ifndef CONTROLLER_H
#define CONTROLLER_H
class ViewDate;
class ModelDate;
class Controller
{
private:
ViewDate* pview;//视图指针指向视图
ModelDate* pmodel; //模式指针指向模式的地址
public:
Controller();
~Controller();
void SetView(ViewDate* pv);//设置视图的地址给pview
void SetModel(ModelDate* pm);//设置模式的地址给pmodel
void Run();//运行
void Now();
void NextMonth();//下一个月
void PrevMonth();//上一个月
void NextYear();//下一年
void PrevYear();//上一年
};
#endif
第二步:再写三个对象的.cpp文件
源文件ModelDate.cpp
#include"ModelDate.h" #include"ViewDate.h" #includeint ModelDate::GetYear() const //获得年份 { return year; } int ModelDate::GetMongth() const//获得月份 { return month; } int ModelDate::GetMday() const { return mday; } int ModelDate::GetCurweek() const { return curweek; } int ModelDate::GetOneweek() const { return oneweek; } int ModelDate::GetMdays() const { return mdays; } bool ModelDate::Is_Leap() const//判断当前的年是否为闰年 { return (year % 4 == 0 && year % 100 == 0) || (year % 400 == 0); } int ModelDate::GetYM_Day() const//根据年和月计算总的天数 { static const int days[]{ 29,31,28,31,30,31,30,31,31,30,31,30,31 };//一年内每个月的天数 常性数组(查表法) //以后每次调用时,都需要初始化,为了避免这种情况,加一个静态关键字static //静态关键字static的特点:生存周期改变了,而可见性没变 int m = month; if (2 == m && Is_Leap())//如果当月是2月,且为闰年 { m = 0;//当月为29天 } return days[m]; } int ModelDate::GetWeek(int d) const//这个月的1号是周几 { int c = year / 100;//取年的世纪 int y = year % 100;//取年的后两位 int m = month; if (m == 1 || m == 2) { m += 12; y--; } return (y + y / 4 + c / 4 - 2 * c + 26 * (m + 1) / 10 + d - 1); } void ModelDate::SetView(ViewDate* pv) { pview = pv;// 将当前的模式指针给对象视图,使其发生关联,只要数据发生改变,即会通知外部视图进行打印 } ModelDate::ModelDate()//构造函数 :pview{ nullptr } { Now();//不进行初始化,直接调用当前时间 } ModelDate::~ModelDate()//析构函数 { } void ModelDate::SetWM() { curweek = GetWeek(mday);//当前是星期几 oneweek = GetWeek(1);//当前年月的1号是星期几 mdays = GetYM_Day();//这一年这一月一共有多少天 } void ModelDate::Now()//获得当前现在的日期 { time_t tt; tm md;//tm结构, time(&tt); localtime_s(&md, &tt); year = md.tm_year + 1900; month = md.tm_mon + 1; mday = md.tm_mday; } void ModelDate::NextYear()//下一年 { year += 1; SetWM();//当年份发生改变,则设置值 对应的星期,总天数都会改变 pview->Event(this); } void ModelDate::PrevYear()//上一年 { if (year > 1) { year -= 1; } SetWM(); pview->Event(this); } void ModelDate::NextMonth()//下一个月 { if (++month > 12) { month = 1; year += 1; } SetWM(); pview->Event(this); } void ModelDate::PrevMonth()//上一个月 { if (--month < 1) { if (year > 1) { year -= 1; month = 12; } } SetWM(); pview->Event(this);//只要数据一发生改变,则发送一个事件 }
源文件ViewDate.cpp
#include"ViewDate.h" #include#include"ModelDate.h" ViewDate::ViewDate() { } ViewDate::~ViewDate() { } int ViewDate::Menum()//显示菜单 { printf("*************************欢迎进入日历*****************************n"); printf("***************************当前日历*******************************n"); printf("************ 0. 按0退出 *******************n"); printf("************ 1. 获取下一个月的日历 *******************n"); printf("************ 2. 获取上一个月的日历 *******************n"); printf("************ 3. 获取下一个年的日历 *******************n"); printf("************ 4. 获取上一个年的日历 *******************n"); printf("************ 5. 当前日历 *******************n"); printf("******************************************************************n"); int n = 0; printf("请输入数字0-5:"); scanf_s("%d", &n); return n; } void ViewDate::PrintDate(int year, int month, int mday, int oneweek, int mdays) const //打印日期 { int n = mdays + oneweek; int d = 1; printf("year: %d month : %d n", year, month); printf("日 一 二 三 四 五 六 n"); for (int i = 1; i <= n; ++i) { if (i <= oneweek) { printf("%5c", ' '); } else { printf("%5d", d++); } if (i % 7 == 0) { printf("n"); } } printf("n"); } void ViewDate::Event(ModelDate* pmodel) { PrintDate(pmodel->GetYear(), pmodel->GetMongth(), pmodel->GetMday(), pmodel->GetOneweek(), pmodel->GetMdays()); }
源文件controller.cpp
#include"Controller.h" #include "ModelDate.h" #include"ViewDate.h" #include第三步:最后在主函数中测试Controller::Controller() :pview{nullptr},pmodel{nullptr} //模式指针和视图指针都置为空 { } Controller::~Controller() { } void Controller::SetView(ViewDate* pv) { pview = pv;//成员指针指向外部对象 } void Controller::SetModel(ModelDate* pm) { pmodel = pm;//模式指针pmodel指向pm } void Controller::Run()//运行 { int select = 0; do { select = pview->Menum(); switch (select) { case 0: break; case 1: NextMonth(); break; case 2:PrevMonth(); break; case 3:NextYear(); break; case 4:PrevYear(); break; default: printf("select errorn"); break; } } while (select != 0); } void Controller::Now() { pmodel->Now();//调用模式端的当前时间 } void Controller::NextMonth()//下一个月 { pmodel->NextMonth();//调用模式段的下一个月 } void Controller::PrevMonth()//上一个月 { pmodel->PrevMonth(); } void Controller::NextYear()//下一年 { pmodel->NextYear(); } void Controller::PrevYear()//上一年 { pmodel->PrevYear(); }
#include#include"Controller.h" #include"ModelDate.h" #include"ViewDate.h" class Client { private: Controller contr; ModelDate model; ViewDate view; public: Client() :contr{}, model{}, view{} { contr.SetModel(&model); contr.SetView(&view); model.SetView(&view); } ~Client() { } void Run() { contr.Run();//调动控制端的运行 } }; int main() { Client client; client.Run(); return 0; }
运行结果如下:



