设计包导出接口的随想

简介:本文讨论在设计一个包的导出接口时遇到的问题以及所采取的解决思路和方法,并提供了模拟代码作为例子。

假设有一个包gameword有个导出结构Player,包含了一些游戏逻辑相关的函数;而且这个Player是可以序列化的。很直接的想法是Player直接实现io.ReadWriter接口,类似这样:

// version 1
package gameworld

type Player struct {


// ...
}
// 序列化函数
func (p *Player) Read(data []byte) (int, error) {

// ...
}
func (p *Player) Write(data []byte) (int, error) {

// ...
}
// 游戏逻辑函数
func (p *Player) Walk() {

// ...
}

这里有一个很明显的问题是:在Player暴露给包使用者的函数中,Read和Write函数是为了序列化而存在的,和Walk等游戏逻辑相关的函数根本没有直接的关联;这样把不同类别的函数都放在Player里大大减弱了对象的内聚性,也对使用者产生了干扰。但是Player又需要实现序列化,也就是要提供io.ReadWriter接口。解决的办法是提供一个全局转换函数,用于把Player对象转换成io.ReadWriter接口。这个转换函数是全局的而不是Player的一个函数,理由同样是为了保持Player对象的内聚性。
// version 2
package gameworld
import "io"
type Player struct {

// ...
}
// 游戏逻辑函数
func (p *Player) Walk() {

// ...
}
// 序列化实现
type playerReadWriter Player
func (p *playerReadWriter) Read(data []byte) (int, error) {

// ...
}
func (p *playerReadWriter) Write(data []byte) (int, error) {

// ...
}
// 转换函数
func SerializePlayer(p *Player) io.ReadWriter {

return (*playerReadWriter)(p)
}

最后,为了使用上的便利,最好能有一个Size函数能够知道player序列化所需要缓冲区字节数的大小。因此把io.ReadWriter和这个Size函数整合成一个新的序列化接口。于是,有了版本3:

// version 3
package gameworld
type Player struct {
// ...
}
// 游戏逻辑函数
func (p *Player) Walk() {


// ...

}
// 序列化实现
type playerReadWriter Player
func (p *playerReadWriter) Read(data []byte) (int, error) {


// ...

}
func (p *playerReadWriter) Write(data []byte) (int, error) {


// ...

}
func (p *playerReadWriter) Size() int {


// ...

}
// 序列化接口
type ReadWriter interface {


Read([]byte) (int, error)


Write([]byte) (int, error)


Size() int

}
// 转换函数
func SerializePlayer(p *Player) ReadWriter {


return (*playerReadWriter)(p)

}
至此,暴露给包外的界面非常的清晰。Player、SerializePlayer和ReadWriter相互独立,各司其职,同时也易于使用。

原文发布于微信公众号 - Golang语言社区(Golangweb)

原文发表时间:2017-02-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏沈唁志

如何优化PHP性能呢?PHP性能优化总结

30330
来自专栏Python攻城狮

Python进程VS线程1.进程和线程2.同步的概念3.互斥锁4.多线程-非共享数据5.同步应用6.生产者与消费者模式

队列: 1、进程之间的通信: q = multiprocessing.Queue() 2、进程池之间的通信: q = multiproc...

12530
来自专栏安恒网络空间安全讲武堂

堆学习入门

借助hitcon training的题目对三种堆的利用方法进行了一个系统的学习,刚入坑的堆小白们可以一起学习一下。题目链接:https://github.com...

16920
来自专栏北京马哥教育

记一次调试python内存泄露的问题

这两天由于公司需要, 自己编写了一个用于接收dicom文件(医学图像文件)的server. 经过各种coding-debuging-coding-debugi...

84970
来自专栏容器云生态

关于vim的简单设置以及使用技巧

vim快速指南: vim 使用技巧: 1、认识.命令 最理想的编辑模式:一次按键移动,一次编辑操作 .命令可以重复上一次的修改操作 在普通模式下: j...

25590
来自专栏我和PYTHON有个约会

20. 企业级开发基础1:自定义模块

之前的课程中,我们已经了解了python程序设计开发的基础部分内容 包含了数据类型、变量、运算符、程序选择结构、循环结构、函数处理、字符串处理等等内容。 本...

9430
来自专栏Python中文社区

一种Python全局配置规范以及其修改

專 欄 ❈丁果,Python中文社区作者。对django、pyqt、opencv、tornado感兴趣。 GitHub:https://github.com/...

33190
来自专栏python3

python 文件操作

新建一个txt文件,内容是《Yesterday When I Was Young》一首歌的歌词

22520
来自专栏ImportSource

并发编程-加锁机制

本文翻译自《Java Concurrency ?In ?Practice》,定期放送 ,让你利用碎片时间悄悄的看了一本书! 我们的文章是系列的。所以先请允许...

32980
来自专栏Jimoer

JVM学习记录-线程安全与锁优化(一)

线程:程序流执行的最小单元。线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源(内存地址、文件I...

8120

扫码关注云+社区

领取腾讯云代金券