一个很小的C++写的MVC的例子

#include<iostream>
#include<vector>

//get namespace related stuff
using std::cin;
using std::cout;
using std::endl;
using std::flush;
using std::string;
using std::vector; 

//struct Observer, modeled after java.utils.Observer
struct Observer
/*
 * AK: This could be a template (C++) or generic (Java 5),
 * however the original Smalltalk MVC didn‘t do that.
 */
{
   //update
   virtual void update(void*)=0;
}; 

 //struct Observable, modeled after java.utils.Observable
struct Observable
{
   //observers
   vector<Observer*>observers; 

   //addObserver
   void addObserver(Observer*a){observers.push_back(a);} 

   //notifyObservers
   void notifyObservers()
   {
    for (vector<Observer*>::const_iterator observer_iterator=observers.begin();observer_iterator!=observers.end();observer_iterator++)
     (*observer_iterator)->update(this);
   } 

  /*
  AK: If you had a method which takes an extra "ARG" argument like this
  notifyObservers(void* ARG), you can pass that arg to each Observer via
  the call (*observer_iterator)->update(this,ARG); 

  This can significantly increase your View‘s reusablity down the track.
  I‘ll explain why below in the View.
  */

}; 

 //struct Model, contains string-data and methods to set and get the data
struct Model:Observable
{
   //data members title_caption, version_caption, credits_caption
   string title_caption;
   string version_caption;
   string credits_caption; 

   //data members title, version, credits
   string title;
   string version;
   string credits; 

   //constructor
   Model() :
    title_caption("Title: "),
    version_caption("Version: "),
    credits_caption("Credits: "),
    title("Simple Model-View-Controller Implementation"),
    version("0.2"),
    credits("(put your name here)")
    { } 

   //getCredits_Caption, getTitle_Caption, getVersion_Caption
   string getCredits_Caption(){return credits_caption;}
   string getTitle_Caption(){return title_caption;}
   string getVersion_Caption(){return version_caption;} 

   //getCredits, getTitle, getVersion
   string getCredits(){return credits;}
   string getTitle(){return title;}
   string getVersion(){return version;} 

   //setCredits, setTitle, setVersion
   void setCredits(string a){credits=a;notifyObservers();}
   void setTitle(string a){title=a;notifyObservers();}
   void setVersion(string a){version=a;notifyObservers();}
  /*
   * AK notifyObservers(a) for credit, title and version.
   * All as per discussion in View and Observer *
   */
};

/*
AK:
Great stuff ;-) This satisfies a major principle of the MVC
architecture, the separation of model and view.

The model now has NO View material in it, this model can now be used in
other applications.
You can use it with command line apps (batch, testing, reports, ...),
web, gui, etc.

Mind you "MVC with Passive Model" is a variation of MVC where the model
doesn‘t get even involved with the Observer pattern.

In that case the Controller would trigger a model update *and it* could
also supply the latest info do the Views. This is a fairly common MVC
variation, especially with we apps.
*/

 //struct TitleView, specialized Observer
struct TitleView:Observer
{
/*
 * AK:
 * I like to get a reference to the model via a constructor to avoid
 * a static_cast in update and to avoid creating zombie objects.
 *
 * A zombie object is instantiated but is unusable because it
 * is missing vital elements. Dangerous. Getting model via the
 * constructor solves this problem.

 Model model;
 // Cons.
 TitleView (Model* m) ....

RE-USABILITY.
Some views are better off working with the full Model, yet others are
better off being dumber.

I like to have two kinds of Views. Those that work with full Model (A)
and those that only work with a limited more abstract data type (B).

Type A.
Complex application specific views are better off getting the full
model, they can then just pick and choose what they need from the full
model without missing something all the time. Convenient.

Type B.
These only require abstract or generic data types.

Consider a PieChartView, it doesn‘t really need to know about the full
Model of a particular application, it can get by with just float
*values[] or vector<float>;

By avoiding Model you can then reuse PieChartView in other applications
with different models.

For this to be possible you must use the 2 argument version of
notifyObservers. See comments on Observer class.

See my Java example NameView. That view only knows about a String, not
the full Model.
*/

   //update
   void update(void*a)
  /*
   *AK:void update(void*a, void*arg) is often better. As per discussion
  above.
   */
   {
   cout<<static_cast<Model*>(a)->getTitle_Caption();
   cout<<static_cast<Model*>(a)->getTitle();
   cout<<endl;
   }
}; 

 //struct VersionView, specialized Observer
struct VersionView:Observer
{ 

 //update
 void update(void*a)
 {
 cout<<static_cast<Model*>(a)->getVersion_Caption();
 cout<<static_cast<Model*>(a)->getVersion();
 cout<<endl;
 }
}; 

 //struct CreditsView, specialized Observer
struct CreditsView:Observer
{ 

 //update
 void update(void*a)
 {
 cout<<static_cast<Model*>(a)->getCredits_Caption();
 cout<<static_cast<Model*>(a)->getCredits();
 cout<<endl;
 }
}; 

 //struct Views, pack all Observers together in yet another Observer
struct Views:Observer
{
 //data members titleview, versionview, creditsview
 TitleView titleview;
 VersionView versionview;
 CreditsView creditsview;
/*
 * AK:
 * Views are often hierarchical and composed of other Views. See
Composite pattern.
 * vector<View*> views;
 *
 * Views often manage (create and own) a Controller.
 *
 * Views may include their own Controller code (Delegate).
 *
*/
 //setModel
 void setModel(Observable&a)
 {
 a.addObserver(&titleview);
 a.addObserver(&versionview);
 a.addObserver(&creditsview);
 a.addObserver(this);
 } 

 //update
 void update(void*a)
 {
 cout<<"_____________________________";
 cout<<"\nType t to edit Title, ";
 cout<<"v to edit Version, ";
 cout<<"c to edit Credits. ";
 cout<<"Type q to quit./n>>";
 }
}; 

 //struct Controller, wait for keystroke and change Model
 struct Controller
/*
 * AK: Controller can also be an Observer.
 *
 * There is much to say about Controller but IMHO we should defer
 * that to another version.
 */
{
   //data member model
   Model*model; 

   //setModel
   void setModel(Model&a){model=&a;} 

   //MessageLoop
   void MessageLoop()
   {
    char c=‘ ‘;
    string s;
    while(c!=‘q‘)
    {
      cin>>c;
      cin.ignore(256,‘\n‘);
      cin.clear();
      switch(c)
      {
       case ‘c‘:
       case ‘t‘:
       case ‘v‘:
       getline(cin,s);
       break;
      }
      switch(c)
      {
       case ‘c‘:model->setCredits(s);break;
       case ‘t‘:model->setTitle(s);break;
       case ‘v‘:model->setVersion(s);break;
      }
    }
   }
}; 

 //struct Application, get Model, Views and Controller together
struct Application
{ 

   //data member model
   Model model; 

   //data member views
   Views views; 

   //data member controller
   Controller controller; 

   //constructor
   Application()
   {
   views.setModel(model);
   controller.setModel(model);
   model.notifyObservers();
   } 

   //run
   void run(){controller.MessageLoop();}
}; 

 //main
int main()
{
  Application().run();
  return 0;
}

一个很小的C++写的MVC的例子,布布扣,bubuko.com

时间: 2024-12-23 13:49:21

一个很小的C++写的MVC的例子的相关文章

一个很小的 截图 库。 只需要依赖 jQuery

https://github.com/xianglgd/imgCut 一个 很小的 截图库,只需要 依赖jQuery. 支持上下左右控制 截图区. 公司的一个需求,时间有限,所以只写了一点. 本来是想找找是否已有现成的 截图插件,可是发现了不少都是功能很多,比较大,功能不是所有都能用上,所以就自己写一个只有核心功能的 截图插件. 以后也会继续添加功能,但是 会分文件,需要什么功能就添加某个文件即可. 后面会继续 更新. 也很欢迎大家来指正 代码中的缺陷.

Snapshot截图软件(一个很小几百k又很好用的的截图工具)

Snapshot截图软件(一个很小几百k又很好用的的截图工具)Snapshotor 是一款免费的截屏工具.软件功能强大,支持截取窗口或一块区域,也可以增加箭头线,多边形,文本等注释.非常使用经常需要截图并编辑的人士使用,如有需要欢迎下载使用. 软件功能1.支持截取窗口或一块区域2.可以增加箭头线,多边形,文本等注释. 大老李影院:www.dalaoli.top大老李博客:www.ldxzs.top 原文地址:http://blog.51cto.com/n1lixing/2147112

一个很小的爬虫,演示了爬一首词,后存进txt文件中去

一个很小的爬虫,演示了爬一首词,后对数据进行清洗,后存进txt文件中去 import requests,refrom bs4 import BeautifulSoup url="https://trade.500.com/sfc/"url2="https://so.gushiwen.org/shiwenv_4d3b4d132c82.aspx" req=requests.get(url2)if req.status_code==200: if req.encoding

为何很大的浮点大数加一个很小的数计算结果不是预期

通常浮点数被表示成N=S*rj S称为尾数,可正可负,j称为阶码可正可负.r是基数,在计算机中取以2的倍数. 计算机中为了提高精度,进行规格化操作:即假设N=11.0101  则规格化表示为N=0.110101*210表示,因为该规格化使得浮点数的表示精度最高. 机器中浮点数由两部分组成:阶码和尾数.基数为2 阶码由阶符跟阶码组成,尾数由数符跟尾数组成 其中阶码是整数,阶符和阶码的位数m合起来反映浮点数的表示范围及小数点的实际位数.尾数是小数,其位数反映了浮点数的精度. 还有机器零这个概念:即浮

【mysql】一个很小但很影响速度的地方

如果要插入一大批数据,千万不要一条一条的execute, commit.而应该是先全部execute,最后统一commit!!! 千万注意,时间差距还是很大的!! 正确示范:快 for i in range(1000000): sql = "INSERT INTO test(a) VALUES(i) self.c.execute(sql) self.db.commit() 错误示范:慢 for i in range(1000000): sql = "INSERT INTO test(a

编译一个很小的可执行文件

C代码: #include <windows.h> #pragma comment(lib, "kernel32.lib") int start() {     TCHAR message[] = TEXT("Taylor Swift\r\n泰勒·斯威夫特");     DWORD toWrite = sizeof(message) - sizeof(TCHAR);     DWORD written;          HANDLE hStdOut =

jquery学习心得:一个很好的css和js函数调用的例子

统一目录下的资源结构图: <html><head> <link rel="stylesheet" href="gallery.css" type="text/css" media="screen" charset="utf-8"/><script type="text/javascript" src="script.js"&g

手把手教你写一个RN小程序!

时间过得真快,眨眼已经快3年了! 1.我的第一个App 还记得我14年初写的第一个iOS小程序,当时是给别人写的一个单机的相册,也是我开发的第一个完整的app,虽然功能挺少,但是耐不住心中的激动啊,现在我开始学react native,那么现在对于react native也算是有所了解了,就用网上的接口开发一个小程序,现在带大家来写这个程序!接口是用看知乎的API,简简单单的只有get,可以从这里入门,也算是带大家入门吧,过后我会把源代码放在我的github上,前期项目肯定特别简陋,后面慢慢来优

「小程序JAVA实战」 小程序手写属于自己的第一个demo(六)

转自:https://idig8.com/2018/08/09/xiaochengxu-chuji-06/ 自己尝试的写一个小demo,用到自定义样式,自定义底部导航,页面之间的跳转等小功能.官方文档对于小程序开发来说要时刻打开https://developers.weixin.qq.com/miniprogram/dev/framework/config.html源码:https://github.com/limingios/wxProgram.git 中的No.1 创建小程序 项目名称创建