许式伟的架构课
许式伟
七牛云 CEO
84945 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 89 讲
许式伟的架构课
15
15
1.0x
00:00/00:00
登录|注册

26 | 实战(一):怎么设计一个“画图”程序?

Create Line, Rect, Ellipse, Circle
Create FreePath
Create Path
Menu, PropSelectors, MousePosTracker
QPaintView 的属性和方法
Controller 接口
QPaintView 类
index.htm 文件
Shape 接口
QPath 类
QEllipse 类
QRect 类
QLine 类
QLineStyle 类
QPaintDoc 类
下一讲将继续实战一个联网版本的画图程序
MVC 框架
概要设计
未依赖任何第三方库
Controller 层
ViewModel 层
Model 层
Github 地址:https://github.com/qiniu/qpaint
Controller 层
View 层
Model 层
结语
架构思维上的学习
浏览器端的 Model,View 和 Controller
画图程序的源代码
桌面程序架构设计的基本结构
内容
作者:七牛云许式伟
标题:26 | 实战(一):怎么设计一个“画图”程序?
参考文章

该思维导图由 AI 生成,仅供参考

你好,我是七牛云许式伟。
到上一讲为止,桌面程序架构设计的基本结构就讲完了。直到现在为止,我们没有讨论任何与具体的应用业务逻辑本身相关的内容。这是因为探讨的内容是普适有效的设计理念,整个讨论会显得很抽象。
今天我们结合一个实际的应用案例,来回顾一下前面我们介绍的内容。
我们选择了做一个 “画图” 程序。选它主要的原因是画图程序比较常见,需求上不需要花费过多的时间来陈述。
我们前面说过,一个 B/S 结构的 Web 程序,基本上分下面几块内容。
Model 层:一个多用户(Multi-User)的 Model 层,和单租户的 Session-based Model。从服务端来说,Session-based Model 是一个很简单的转译层。但是从浏览器端来说,Session-based Model 是一个完整的单租户 DOM 模型。
View 层:实际是 ViewModel 层,真正的 View 层被浏览器实现了。ViewModel 只有 View 层的数据和可被委托的事件。
Controller 层:由多个相互解耦的 Controller 构成。切记不要让 Controller 之间相互知道对方,更不要让 View 知道某个具体的 Controller 存在。
画图程序的源代码可以在 Github 上下载,地址如下:
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文通过介绍一个“画图”程序的实际应用案例,展示了如何设计浏览器端的Model、View和Controller。在Model层,详细介绍了浏览器端的Model层代码及其支持的能力,包括添加图形和绘制。在ViewModel层,重点介绍了QPaintView类的规格和功能,包括与Model层的关联、数据属性、绘制功能以及Controller相关功能。在Controller层,介绍了各种命令菜单和状态显示用途的界面元素,以及创建各类图形的Controller。文章强调了不依赖第三方库的JavaScript代码编写,以及架构设计中的概要设计阶段的重要性。通过对“画图”程序的解剖,建立了桌面程序框架上非常一致的套路,强调了MVC架构对于桌面程序的适用性。文章结合实例介绍了MVC架构,展示了单机版的画图程序,为下期实战一个联网版本的画图程序做了铺垫。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《许式伟的架构课》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(38)

  • 最新
  • 精选
  • 田常发
    许老师,我想问一下,学go的话要不要去学一下,设计模式,有的话,您有没有什么资料可以推荐一下?

    作者回复: 学什么语言都要设计模式。不过设计最重要的不是模式,而是关于解耦的思考

    2019-07-23
    5
    46
  • xiaobang
    这一章看的有点卡,主要是因为对前端知识不熟悉。我看到js代码里面出现class关键字一度怀疑用的是什么语言。另外提一个建议,老师讲的时候能不能按照软件设计的过程来展开。比如开始做需求分析,这个画图程序要提供哪些功能,支持哪些图形等。然后列出平台对画图的支持,再描述在平台上直接硬写会写成什么样的程序,最后按mvc模式重构。我感觉这样能更好的表现设计的思路。

    作者回复: 多谢建议

    2019-07-24
    21
  • Linuxer
    由Controller来创建具体Shape这样会不会,model和controller又耦合了呢

    作者回复: controller本来就会耦合model和view。重点是controller之间不要耦合

    2019-07-19
    16
  • Smallfly
    下载源码并切换到 v26 分支,用浏览器打开 index.html 文件,可使用开发者工具进行断点调试。 绘制矩形的过程:  1. 点击 `Creat Rect` 按钮,激活 react.js(Controller);  2. view.js(View) 接收到 drawing 的 onmousedown 事件,传递给事件的实现者 react.js;  3. react.js 接收到 onmousedown 事件,记录起始点 p1;  4. 同理,react.js 接收到 onmousemove 事件,记录 p2, 并调用全局函数 invalidate 绘制;  5. invalidate 交给 qview.invalidateRect 处理(为什么不直接调用 qview.invalidateRect?);  6. qview.invalidateRect 调用 qview.onpaint,在 onpaint 中调用当前激活的 rect.js 的 onpaint 方法;  7. rect.js 中 onpaint 调用 buildShape() 创建 QRect(Model) 实例,然后调用该实例的 onpaint 方法绘制;  8. 绘制结束时 react.js 接收到 onmouseup 事件,把当前 model 实例存入 doc(Model),保证重绘时能够再次绘制原来的图形; MVC 角色的通信过程: V -> C -> V -> C -> M

    作者回复: react.js => rect.js

    2019-08-17
    4
    15
  • Smallfly
    五讲画图程序已经讲完了,第一次只是泛泛而读,这次打算精读,并整理一下自己的理解。 第一讲的重点架构思想包括:  1. 为了避免 Model 知道 View 的实现细节,可以让 Model 耦合 GDI 接口。模块间通信如果避免不了耦合,就耦合稳定的模块,这个模块最好是系统的,因为系统模块相对于业务模块通常更加稳定;  2. ViewModel 持有 Model,并由 Controller 来更新 Model/ViewModel;  3. ViewModel 定义 Controller 的行为规则,但并不关心 Controller 的具体行为。Controller 可以选择性的接管 ViewModel 的事件;  4. ViewModel 协调 Model 和 Controller,启到承上启下的作用,所以 ViewModel 职责的划分对程序的结构有比较大的影响;  5. Model 的结构稳定,容易做到平台无关,ViewModel 会跟平台强关联;  6. 避免 Controller 之间的耦合,可以使用 ViewModel 作为通信中介者;  7. 相同的 Model 可能在 Controller 层有不同的展现方法; 本讲中 View 应该理解为 ViewModel,View 是不应该持有 Model 数据的,文中老师也说了网页的 View 是由浏览器实现的,个人觉得从严格意义上将,这不算是 MVC 模式,也不像 MVVM,应该叫 MVMC? 下载源码并切换到 v26 分支,用浏览器打开 index.html 文件,可使用开发者工具进行断点调试。

    作者回复: 👍

    2019-08-17
    13
  • Geek_88604f
    看了几遍捋一下思路:view接收到用户事件,把事件处理委托给controller,由controller来操作model。是这样的吗,老师?

    作者回复: 是的

    2019-08-06
    2
    7
  • Geek_88604f
    浏览器打开index.htm,首先创建canvas画布对象,后面的画图操作都是在画布对象上进行的。 接着加载dom对象,注意这里并没有实例化dom对象。 然后加载view对象,并且实例化view对象和dom对象。view对象中定义了事件处理规则,接管画布的事件处理,将onpaint委托给了doc和contraller,注意doc的onpaint和contraller的onpaint绘制的是不同的内容,还有就是定义了contraller的操作规则。 接下来就是加载contraller,调用view的方法注册自己,并将事件处理委托给contraller。 最后加载和显示菜单,定义contraller的鼠标点击事件,在点击事件中指定当前contraller。这样当鼠标在画布上移动时,通过层层委托(画布——view——contraller)最终触发contraller的invalidate,invalidate触发onpaint,onpaint触发doc.onpaint。

    作者回复: 👍

    2019-08-10
    2
    5
  • Jian
    最大的收获还是解耦。首先将应用程序进行抽象/分层,然后通过中间的view层将model层和controller层串联在一起。 controller的使用,就像java中的interface,其有多重实现方式。 这是第二次读这篇文章了,因为没有接触过前端,不知道前端的实习方式。后面看懂了代码,但是如果能有个流程图样的粗略解释可能会更有利于理解吧。

    作者回复: 多谢建议

    2019-08-01
    2
  • méng
    看了一些评论,得到一个理解,不知道对不对:这里的mvc只讨论分工,相当于是把领域的功能按职责分工。model是业务的核心,它与平台无关。controller是领域服务,即根据具体的也许行为提供调度服务。view层则是针对具体的可视化平台响应操作。 v调用c调用m

    作者回复: v不会主动感知c。m+v构成只读的软件,然后v只是无脑委托事件交给c,c来实现真正意义上的用户交互

    2021-09-21
    2
    1
  • méng
    老师,可能我习惯了web开发那套mvc,对于文章里提的mvc总感觉对不上号。这里边说的mvc是指一个类里边分别对应视图控制器模型的归类吗?

    作者回复: 在web中,从架构视角来说api服务层是model层(当然有很多公司不提供api服务层,这个时候应该认为model层由数据库实现,和单机软件controller直接访问变量的getter/setter来说,属于贫血的model层。view层主要是模板引擎,它关注的是data(dom)如何渲染成html+js,并且让界面操作的事件关联上对应的controller。剩下来的东西基本上都应该归类为conroller层。对于胖前端(用js实现业务),js就是controller。对于胖后端(比如用php实现业务),php就是controller。这一层最重要的是解耦,如何让不同controller实现无关,不会彼此耦合得很死。

    2021-09-21
    1
收起评论
显示
设置
留言
38
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部