大家都是做GUI开发的,都应该了解模型/视图架构编程,但是大家了解它的起源吗?
其实MVC框架在1982年就已经诞生了是起源于Small talk语言的框架,现在已经成为了一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件中,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
然后MVC框架火了,Smalltalk却失败了。
大家可能都没听过Smalltalk,但是它其实是公认的历史上第二个面向对象的程序设计语言(第一个是Simula67,估计大家也没听过)和第一个真正的集成开发环境(IDE),它对其它众多的设计语言的产生起到了极大的推动作用。
对Smalltalk的扩展小知识我放到了博客的最后,大家可以当科普读一下,了解一下面向对象的起源
在MVC之前,用户界面都是将3种组件集合在一起,MVC将它们分开,从而提高了灵活性和重用性。
如果将视图和控制这两种组件结合起来,就形成了模型/视图框架。这同样将数据的存储和数据向用户的展示进行了分离,但提供了更为简单的框架。
数据和界面进行分离。使得相同的数据在多个不同的视图中进行显示成为可能,而且还可以创建新的视图,而不需要改变底层的数据框架。
为了对用户输入进行灵活处理,还引入了委托(Delegate)的概念,使用它可以定制数据的渲染和编辑方式。
其中每一个组件都使用了一个抽象类来定义,提供了一些通用接口和一些功能的默认实现,
模型、视图、代理组件之间通过信号和槽来实现通信:
Qt的所有模型类都是基于QAbstractItemModel虚类,这个定义了接口,可以供视图和代理来访问数据。
Qt提供了一些现成的模型来处理数据项:
如果Qt提供的这些标准模型无法满足需要,还可以子类化QAbstractItemModel、QAbstractListModel或者QAbstractTableModel来创建自定义的模型。
为了确保数据的表示与数据的获取相分离,Qt引入了模型索引的概念。
每一块可以通过模型获取的数据都使用一个模型索引来表示,视图和委托都使用这些索引来请求数据项并显示。
模型索引有QModelIndex类提供,它是对一块数据的临时引用,可以用来检索或修改模型中的数据。
因为模型可以随时对内部的结构进行重新组织,这样模型索引可能失效,所以不需要也不应该存储模型索引
Qt提供了几种不同类型的视图:
模型/视图架构中对项目的选择提供了非常方便的处理方法。在视图中被选择的项目的信息存储在
Q
I
t
e
m
S
e
l
e
c
t
i
o
n
M
o
d
e
l
QItemSelectionModel
QItemSelectionModel实例中,这样被选择项目的模型索引变保持在一个独立的模型中,与所有的视图都是独立的。在一个模型上设置多个模型时,就可以实现在多个视图之间共享选择。
选择由选择范围指定,只需要记录每一个选择范围开始和结束的模型索引即可,非连续的选择可以使用多个选择范围来描述。选择可以看作是在选择模型中保存的一个模型索引集合,最近的项目被称为当前选择。
在模型/视图框架中,QAbstractItemDelegate是委托的抽象基类,
默认的委托实现由QStyledItemDelegate类提供,这也被叫做Qt标准视图的默认委托。
然而,QStyleItemDelegate和QItemDelegate是相互独立的。只能选择其一来为视图中的项目绘制和提供编辑器。它们的主要不同就是,QStyledItemDelegate使用当前的样式来绘制项目,因此,当要实现自定义的委托要和Qt样式表一起应用时,建议使用QStyleItemDelegate作为基类。
与MVC模式不同,模型/视图结构中没有包含一个完整分离的组件来处理与用户的交互。一般的,视图用来将模型中的数据展示给用户,也用来处理用户的输入。
为了获得更高的灵活性,交互可以由委托来执行。这些组件提供了输入功能,而且也负责渲染一些视图中的个别项目。控制委托的标准接口在QAbstractItemDelegate类中定义。
委托通过实现painter()和sizeHint()函数来使它们可以渲染自身的内容。然而,简单的基于部件的委托可以通过子类化QItemDelegate来实现,而不需要使用QAbstractItemDelegate,这样可以使用这些函数的默认项实现。委托的编辑器可以通过两种方式来实现,一种是使用部件来管理编辑过程,另一种是直接处理事件。可以参考Qt提供的Spin Box Delegate Example示例程序来理解第一种形式。如果想继承QAbstractItemDelegate来实现自定义的渲染操作,那么可以参考Pixelator Example示例程序。另外,还可以使用QStyledItemDelegate作为基类,这样可以自定义数据的显示,这个可以参考Star Delegate Example示例程序。
Qt中的标准视图都使用QItemDelegate的实例来提供编辑功能,这种委托接口的默认实现为QListView、QTableView和QTreeView等标准视图的每一个项目提供了普通风格的渲染。标准视图中的默认委托会处理所有的标准角色,具体的内容可以在QItemDelegate类的帮助文档中查看。可以使用itemDelegate()函数获取一个视图中使用的委托,使用setItemDelegate()函数可以为一个视图安装一个自定义委托。
讲起源就不得不讲Simula67这个语言了,它第一次提出了对象这个概念。
计算机科学中对象和实例概念的最早萌芽可以追溯到麻省理工大学的PDP-1系统。这一系统大概是最早的基于容量架构(capability based architecture)的实际系统。另外1963年Ivan Sutherland的Sketchpad应用中也蕴含了同样的思想。
对象作为编程实体最早是于1960年代由
S
i
m
u
l
a
67
Simula 67
Simula67语言引入思维。
S
i
m
u
l
a
Simula
Simula这一语言是
O
l
e
−
J
o
h
a
n
D
a
h
l
Ole-Johan Dahl
Ole−JohanDahl和
K
r
i
s
t
e
n
N
y
g
a
a
r
d
Kristen Nygaard
KristenNygaard在挪威奥斯陆计算机中心为模拟环境而设计的。
(据说,他们是为了模拟船只而设计的这种语言,并且对不同船只间属性的相互影响感兴趣。他们将不同的船只归纳为不同的类,而每一个对象,基于它的类,可以定义它自己的属性和行为。)
这种办法是分析式程序的最早概念体现。在分析式程序中,我们将真实世界的对象映射到抽象的对象,这叫做“模拟”。Simula不仅引入了“类”的概念,还应用了实例这一思想——这可能是这些概念的最早应用。
20世纪70年代施乐 P A R C PARC PARC研究所发明的 S m a l l t a l k Smalltalk Smalltalk语言将面向对象程序设计的概念定义为,在基础运算中,对对象和消息的广泛应用。
S
m
a
l
l
t
a
l
k
Smalltalk
Smalltalk的创建者深受
S
i
m
u
l
a
67
Simula 67
Simula67的主要思想影响,但Smalltalk中的对象是完全动态的——它们可以被创建、修改并销毁,这与
S
i
m
u
l
a
Simula
Simula中的静态对象有所区别。
此外,
S
m
a
l
l
t
a
l
k
Smalltalk
Smalltalk还引入了继承性的思想,它因此一举超越了不可创建实例的程序设计模型和不具备继承性的
S
i
m
u
l
a
Simula
Simula。
感觉 s m a l l t a l k smalltalk smalltalk的失败完全是一个偶然,因为 s u n sun sun公司不肯付出大价钱安装 s m a l l t a l k 80 smalltalk 80 smalltalk80系统,如果当时 s u n sun sun要是采用了 s m a l l t a l k smalltalk smalltalk,今天的面向对象编程估计都是 s m a l l t a l k smalltalk smalltalk系列了
虽然
s
m
a
l
l
t
a
l
k
smalltalk
smalltalk的原始版本没有广泛为人们所知道,但是它的优点和其他变体无处不在和一些遗留技术,
最初给
s
m
a
l
l
t
a
l
k
80
smalltalk 80
smalltalk80编写
j
i
t
jit
jit编译器的哥们后来又编写了谷歌的v8引擎,这个v8引擎因为性能好后来又烧到了服务器端成为了
n
o
d
e
j
s
nodejs
nodejs的核心,有一家做创业公司的
s
m
a
l
l
t
a
l
k
smalltalk
smalltalk编译器被
s
u
n
sun
sun收购之后,成为了
j
a
v
a
虚
拟
机
的
一
部
分
(
h
o
t
s
p
o
t
)
java虚拟机的一部分(hotspot)
java虚拟机的一部分(hotspot),
最出名的就是微软和苹果赖以发家的窗口化图形用户界面,
s
m
a
l
l
t
a
l
k
smalltalk
smalltalk之所以会诞生所谓面向对象编程和图形用户界面,甚至是专门的即时编译技术,都是源于它本身的特点.
最初的语言系统里面,和
C
C
C 语言还有
u
n
i
x
unix
unix系列不一样,它的语法是由类本身产生,在混合了数据和代码的系统里面,操作系统被编程语言纳入其中,一个类负责一个功能,就是一个编程语言,一个特定的系统,
比如说最初的系统内部,没有文件系统,没有进程控制,自动内存回收,所有的一切都是一个
i
m
a
g
e
image
image世界,里面有一堆对象,当你开发好一个软件之后,你可以直接保存给别人在他的磁盘上打开,或者你也可以通过网络分享“活的”对象给别人,这个对象就是一个类实例化之后的代码,它在本质上是一个函数,具有特定的输入输出,只要在具有宿主环境的条件下,解析出来生成它,用户就得到了这个对象,他可以使用这个对象完成自己需要的工作,如果我们把
u
n
i
x
unix
unix系统比喻成卖工厂的国家,
s
m
a
l
l
t
a
l
k
smalltalk
smalltalk就好像是专门卖螺丝刀的,你可以自己自由选择需要的工具,完成自己的工作,这些对象之间的通信接口与语言的标准完全一致,不必要为各种各样的系统之间的通信繁复地编码解码了。
但是面对对象语言也不是缺点,面对对象最大的问题就是混淆了数据和逻辑,程序员们认为对象是逻辑的集合体而忘记了对象还是数据的载体。
造成的后果就是大量不懂计算机原理的程序员滥用对象爆掉内存,如果计算机的内存只有几百MB甚至只有几十MB,对内存没有概念的不会管理的程序员根本罩不住。
所以现在的嵌入式仍是C系列的天下,仍是资深程序员的天堂,学习内存的管理和计算机底层原理根本不是那些非科班就花几个月时间能学的明白的。
现在很多低代码软件和便捷的开发语言降低了开发门槛,一个完全不懂代码的人通过几个月的学习就能开发一个业务系统,但是代码的高深之处不是这些速成的程序员能祸害的。
这也难怪优秀的设计模式和架构都是国外编码的成功经验,而国内基本没有,因为优秀的资深程序员都TM转行了!!!
我们现在的编码环境太差了,程序员本来就是一个需要日积月累的工作岗位,现在企业用的都是一些完全不懂代码的新人,35岁的岗位危机害了多少资深程序员(还炫耀企业组成都是年轻人之类的),看看国外六七十的程序员比比皆是,他们才是整个代码世界的支柱,我们不能仅仅关注面向业务的代码,认为TMD快速开发才是对的(重构时麻烦的要死,代码写的垃圾的一匹),我们更应该编好的代码做一个好程序员!!!
查资料的时候突然看到了对国内编码环境的思考,有感而发,大家见谅~