37 | 编程范式游记(8)- Go 语言的委托模式
下载APP
关闭
渠道合作
推荐作者
37 | 编程范式游记(8)- Go 语言的委托模式
2018-02-06 陈皓 来自北京
《左耳听风》
课程介绍
讲述:杨超
时长04:00大小3.65M
你好,我是陈皓,网名左耳朵耗子。
我们再来看 Go 语言这个模式,Go 语言的这个模式挺好玩儿的。声明一个 struct,跟 C 很一样,然后直接把这个 struct 类型放到另一个 struct 里。
委托的简单示例
我们来看几个示例:
由上面可知:
我们声明了一个 Widget,其有 X和Y;
然后用它来声明一个 Label,直接把 Widget 委托进去;
然后再给 Label 声明并实现了一个 Paint() 方法。
于是,我们就可以这样编程了:
我们可以看到,如果有成员变量重名,则需要手动地解决冲突。
我们继续扩展代码。
先来一个 Button:
再来一个 ListBox:
然后,声明两个接口用于多态:
于是我们就可以这样泛型地使用(注意其中的两个 for 循环):
一个 Undo 的委托重构
上面这个是 Go 语言中的委托和接口多态的编程方式,其实是面向对象和原型编程综合的玩法。这个玩法可不可以玩得更有意思呢?这是可以的。
首先,我们先声明一个数据容器,其中有 Add()、 Delete() 和 Contains() 方法。还有一个转字符串的方法。
我们如下使用这个数据容器:
这个数据容器平淡无奇,我们想给它加一个 Undo 的功能。我们可以这样来做:
于是就可以这样使用了:
但是,需要注意的是,我们用了一个新的 UndoableIntSet 几乎重写了所有的 IntSet 和 “写” 相关的方法,这样就可以把操作记录下来,然后 Undo 了。
但是,可能别的类也需要 Undo 的功能,我是不是要重写所有的需要这个功能的类啊?这样的代码类似,就是因为数据容器不一样,我就要去重写它们,这太二了。
我们能不能利用前面学到的泛型编程、函数式编程、IoC 等范式来把这个事干得好一些呢?当然是可以的。
如下所示:
我们先声明一个 Undo[] 的函数数组(其实是一个栈);
并实现一个通用 Add()。其需要一个函数指针,并把这个函数指针存放到 Undo[] 函数数组中。
在 Undo() 的函数中,我们会遍历Undo[]函数数组,并执行之,执行完后就弹栈。
那么我们的 IntSet 就可以改写成如下的形式:
然后在其中的 Add 和 Delete中实现 Undo 操作。
Add 操作时加入 Delete 操作的 Undo。
Delete 操作时加入 Add 操作的 Undo。
我们再次看到,Go 语言的 Undo 接口把 Undo 的流程给抽象出来,而要怎么 Undo 的事交给了业务代码来维护(通过注册一个 Undo 的方法)。这样在 Undo 的时候,就可以回调这个方法来做与业务相关的 Undo 操作了。
小结
这是不是和最一开始的 C++ 的泛型编程很像?也和 map、reduce、filter 这样的只关心控制流程,不关心业务逻辑的做法很像?而且,一开始用一个 UndoableIntSet 来包装IntSet类,到反过来在IntSet里依赖Undo类,这就是控制反转 IoC。
以下是《编程范式游记》系列文章的目录,方便你了解这一系列内容的全貌。
分享给需要的人,Ta购买本课程,你将得29元
生成海报并分享
赞 20
提建议
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
上一篇
36 | 编程范式游记(7)- 基于原型的编程范式
下一篇
38 | 编程范式游记(9)- 编程的本质
精选留言(17)
- milley2018-02-06这样的代码和思维只能说赏心悦目!31
- 小文同学2020-11-041、文章说了什么? 文章分了两部分,一部分先简单说了 Golang 的委托用法。简单来说,就是讲一个 structA 嵌套到另外一个 structB 中,structB 会自动继承 structA 的字段。其后,通过一个更加复杂的例子说明委托的用法。(作为一个 Java 程序员,Golang 为 struct 增加方法,和定义接口的方法让人印象深刻) 另一部分,作者举了一个更加复杂的例子说明 Go 中委托和接口多态是如何实现一个数据容器的 Undo 实现的。为了说明这部分,作者通过以下步骤一说说进阶说明: 1、最简单的一个 IntSet,并定义了 Add ,Delete 方法; 2、通过一个委托的方法,将 IntSet 委托给一个新的 struct,新 struct 再重写一次 Add,Delete 方法以记录步骤(保存Undo函数对象),完成 Undo 功能; 3、最后作者希望可以进一步改写,编写一个 Undo 栈,委托给 IntSet ,并在 IntSet 编写 Add,Delete 的方法中就完成 Undo 函数对象的保存。这也是一个实现方法。展开9
- Jie2020-11-11求教,最后那段代码执行undo的时候会继续添加undo函数,那样不就回不到最初的状态了?后续一直在撤销undo—撤销撤销undo……2
- 拉欧2019-05-29go里面这个undo功能的实现类似scala里面的trait,也是把一些功能模块(以及实现)单独封装起来,然后以委托或者继承的形式组装到类里面,这种灵活组装的方式确实比java的interface要更方便使用,不同语言之间是有共同点的3
- Jacob.C2021-03-05再在undo里加个反撤销的功能,就更秀了1
- 亢(知行合一的路上)2019-02-26依赖的东西要可靠、稳定,也就是接口。 业务与控制分离,控制就可以复用。 把变化频率不同的事物分开。2
- 寻找的人cs2019-02-06web端功能多一点就好了,比如显示文章列表的时候感觉不如app端那么清爽2
- Z32018-02-06sort.Ints(ints) parts := make([]string, 0, len(ints)) for _, i := range ints { 这块要sort吗? 能否直接for (i=0;i<len)print ints[i]1
- 小破2018-02-06几个月前听到代码时间做节目,陈老师讲的内容让我感觉很实在,今天终于跟过来了😃1
- seedjyh2021-10-20委托模式其实就是利用了go的组合功能实现了类似C++的继承功能。就undo数组而言,继承了基类的栈、注册undo的方法和执行undo的方法。
- seedjyh2021-10-20最后的undo数组很有意思。 在C++里,一般是基类Undoable有一个public的实体函数Undo和一个private的纯虚函数undo,前者调用后最后;各个需要undo的子类实现这个纯虚函数。但这样就引入了强耦合(继承)。 在go里是注册一个闭包,让Undo数组回调。
- Geek_bc461b2020-12-16单从undo功能来说用装饰器模式是不是更好
- 你为啥那么牛2020-09-15写了半年的go语言了,终于体会到go语言的美感了。那种只要会嘎嘎叫的,我就认为是一只🦆的境界。😃1
- 高科2020-04-27不久前刚刚把go的环境搭好,部署了一个开源应用,准备学习起来
- whiledoing2020-02-23有点不理解,为什么 Undo 的函数不是直接 delete(set.data, x),而是 set.Delete(x),这样子会不会导致undo 的队列一直在递归共 2 条评论
- xiao豪2018-02-08声明为type Inset map[int]bool就不用写成set.data[x]=true这样了,直接set[x]=true就可以了。
- 小虾米2018-02-06这样写的undo在第一次插入过后,可以无限撤销了吧