LVGL中的一些设计原则
上上周在改一个框架,当然,是基于别人的框架来改,改了两天之后发现有点不太对劲,把原有框架的拓展性改没了。然后就去重新刷了下设计原则。当然,我们的框架不需要太多的拓展性,因为太多的拓展性意会让使用的难度变大,这些就是满大街的大而全的通用框架,面向的是能用的场景;我们框架的目标可能就是对特殊场景的优化,然后让人简单的设置就能用起来。
软件设计七大原则
设计原则 | 定义 | 目的 |
---|---|---|
开闭原则 | 对扩展开放,对修改关闭 | 降低维护带来的新风险 |
依赖倒置原则 | 高层不应该依赖低层,要依赖于抽象,不要依赖于具体实现(面向接口编程) | 更利于代码结构的升级扩展 |
单一职责原则 | 一个类只干一件事,实现类要单一 | 便于理解,提高代码的可读性 |
接口隔离原则 | 一个接口只干一件事,接口要精简单一 | 功能解耦,高聚合、低耦合 |
迪米特法则 | 最少知识原则,不该知道的不要知道,一个类应该保持对其它对象最少的了解,降低耦合度 | 只和朋友交流,不和陌生人说话,减少代码臃肿 |
里氏替换原则 | 不要破坏继承体系,子类重写方法功能发生改变,不应该影响父类方法的含义 | 防止继承泛滥 |
合成复用原则 | 尽量使用组合或者聚合关系实现代码复用,少使用继承 | 降低代码耦合 |
设计原则和设计模式的关系
设计模式分类:
- 创建型模式:工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式
- 结构型模式:适配器模式、桥接模式、过滤器模式、组合模式、装饰器模式、外观模式、享元模式、代理模式
- 行为型模式:责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、空对象模式、策略模式、模板模式、访问者模式
关系:
设计模式是设计原则的应用、实现。设计原则是底层原则、是根本;设计模式里面的套路用了设计原则。简单的讲,你写的代码可以没有使用设计模式,但一定不能没有设计原则
C语言和面向对象
先讨论下C++
C++作者:Bjarne Stroustrup
![](/assets/image-20220321164258684.D8VHQc8O.webp)
C++是一个多范式的语言;包括支持面向对象,也被有人称为“C with Classes”;
CFront:C++原始的编译器,作用把C++代码转成C代码;为啥叫CFront?在C的编译器前面加了一个编译器,把C++代码通过CFront转成C代码,然后用C编译器去编译生成程序
![](/assets/image-20220321165435232.CGEw2PkZ.webp)
面向对象:
问题:C++中的高级特性如何在C中表示?
- 类里面的函数真的属于这个Class吗?
sizeof()
- 类中的
this
怎么来的?语法糖而已;有些语言会显示写self
(Python、Rust) - 类调用成员函数是怎么回事?语法糖,和调用普通全局函数并没有什么区别
![](/assets/image-20220322004626246.D9Bd5Ygo.webp)
C++的虚函数、Java的Interface,Rust的Trait
父类定义接口,然后子类有不同的实现,在实际运行的时候会调用不同的子类实现, 下图中的接口函数本质上是一个函数指针变量,在使用时指定了不同的子类的实现的函数
![](/assets/image-20220323232530466.DWbIXFYv.webp)
设计原则和LVGL
S单一职责:
一个类只负责完成一个职责或者功能
- 目录的命名
- 源代码文件的命名
依赖倒置原则:
定义:高层不应该依赖低层,要依赖于抽象,不要依赖于具体实现(面向接口编程)
目的:更利于代码结构的升级扩展
问题:依赖于抽象?这里的抽象指的是什么?
LVGL中扩展使用:
- lvgl如何显示到不同的屏幕?
- lvgl如何获取不同屏幕的点击坐标?
- lvgl如何显示不同格式的图片?
lvgl如何显示到不同的屏幕?
框架怎么写?
- xxx
- xxx
- 显示到屏幕(估计就会写死)
- xxx
![](/assets/image-20220323231930688.DR_cjuji.webp)
改完后?
- LVGL框架定义接口:
void (*flush_cb)(struct _disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
- 我框架内部会在需要的时候去调这个函数
- 把对应的数据给你:哪块区域的屏幕要刷新
area
,以及这块区域对应的数据值color_p
- 对应的拓展自己去处理数据:通过SDL刷到屏幕;通过Framebuffer刷到屏幕:和不同平台,实现相关
lvgl如何获取不同屏幕的点击坐标?
框架怎么写?
- xxx
- xxx
- 获取屏幕点击的坐标(估计就又会写死)
- xxx
![](/assets/image-20220323231930688.DR_cjuji.webp)
改完后?
- LVGL框架定义接口:
bool (*read_cb)(struct _lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
- 我框架内部会在需要的时候去调这个函数
- 我框架把这个结构体指针
data
给你:你负责把对应点击的坐标填进去,然后我框架内部要用(传递到对应控件的点击回调函数)
- 具体的实现如何去填充数据
上面两者的区别:
- 显示:一个是把数据给你,实现负责去使用这些数据
- 点击:我把结构休指针给你,实现负责把数据填充进去
lvgl如何显示不同格式的图片?
通过实现图片解码器,实现对应函数回调。步骤同上......
现实生活:公司做项目的例子
- 依赖反转前:我领导依赖于我,我的任务完成了,他的项目才能算完成
- 依赖反转后:我领导提出标准,提供对应的资源;我拿到标准和资源,然后去实现
![](/assets/image-20220324000531092.DPrOQNJy.webp)
一开始领导依赖于我的工作,他的任务就算完成;我依赖于我领导给的标准和资源去完成这个任务;另外的一个变化是:对于前者,你的领导可能会控制你的细节(不能用这个,得用那个;不能这样搞,要那样搞);对于后者,我领导就成了标准的制定者
抽象的定义:
- 需要对业务有足够的了解,对问题抽象
- 回调中的参数:能够实现拓展;不要出现冗余的参数
- 抽象标准的要求
- Android的UI线程:死循环不停的去调回调,用户写的ui代码,用户写的事件代码;这些代码得满足一定的要求,比如说:不能卡太久;你卡住了,我内部的死循环就被这个卡死