关于go:精通-Golang-适配器模式

22次阅读

共计 2543 个字符,预计需要花费 7 分钟才能阅读完成。

原文首发于我的博客:https://kaolengmian7.com/post…

示例代码曾经上传到我的 Github:https://github.com/kaolengmian7/golang-demo/tree/master/design_pattern/adapter, 能够把代码拉下来跑一跑~

核心思想

适配器是两个不兼容的接口之间的桥梁,使接口不兼容的对象可能相互合作。

应用场景

有动机地批改一个失常运行的零碎的接口,这时应该思考应用适配器模式。
1. 封装有缺点的接口
2. 封装多个接口
3. 替换依赖
4. 兼容老版本接口
5. 适配不同格局数据

肯定要留神:适配器为的是解决正在退役的我的项目的问题,而不是在设计阶段增加的。如果在设计阶段就思考应用适配器模式,那这个设计肯定不合格。

实战

如果你正在开发一款股票市场监测程序,它会从不同起源下载 XML 格局的股票数据,而后向用户呈现出好看的图表。

type XmlHandler interface {ProcessXml(xml string)}

type xmlHandler struct{}

func (x *xmlHandler) ProcessXml(xml string) {log.Printf("xml:%s processing", xml)}

在开发过程中,你决定在程序中整合一个第三方智能剖析函数库。然而遇到了一个问题,那就是剖析函数库只兼容 JSON 格局的数据。

// 剖析库接口
type JsonHandler interface {ProcessJson(json []byte)}

type jsonHandler struct {
}

func (j *jsonHandler) ProcessJson(json []byte) {log.Printf("json processing")}

你能够批改函数库来反对 XML。然而,这可能须要大量代码。或者,咱们能够将 XML 转换成 JSON?

xml 与 json 代表了事实中不兼容的两个接口。
为了演示不便,我用 string 类型 示意 xml 文件,用[]byte 示意json 文件

适配器就是为两个兼容两个接口而生,在此例中:xmlAdapter继承了XmlHandler 接口,其中封装了对接口的解决。后果就是,客户端的 JSON 解决被“适配”成 XML 解决。

type xmlAdapter struct {JsonHandler}

func (x *xmlAdapter) ProcessXml(xml string) {
 // 模仿对象转换:xml -> json
 json := []byte(xml) // 解决 json 文件
 x.ProcessJson(json)}

func TestAdapter(t *testing.T) {inputJson := []byte("json_file") // 原客户端
 handler := &jsonHandler{} handler.ProcessJson(inputJson)
 // 客户端接入适配器,利用 原有的 JsonHandler 解决 xml 文件。inputXml := "xml_file" adapter := &xmlAdapter{&jsonHandler{}} adapter.ProcessXml(inputXml)}

长处

灵活性强,上线新性能不须要改变大量源代码,仅须要在接口层做一层类型转换。

毛病

过多地应用适配器,会让零碎十分零乱。比方,表明上看到调用的是 A 接口,其实外部被适配成了 B 接口的实现。
一个零碎如果太多呈现这种状况,无异于一场劫难。因而如果不是很有必要,尽量不应用适配器,而是间接对系统进行重构。

更进一步:加强版适配器

对于 Golang 这种能够实现多继承的语言来讲,适配器有更优雅的解决方案:让适配器实现所有接口。

type adapter struct {jsonHandler JsonHandler xmlHandler  XmlHandler}

这样的适配器弱小的多,想用谁的实现就用谁的实现,与此同时齐全躲避了下面提到的毛病,不容易产生误解。

func TestAdapterInGolang(t *testing.T) {inputJson := []byte("json_file") inputXml := "xml_file" // 原客户端
 handler := &jsonHandler{} handler.ProcessJson(inputJson)
 // 客户端接入适配器
 adapter := &adapter{&jsonHandler{}, &xmlHandler{}} adapter.jsonHandler.ProcessJson(inputJson) // 想用 json 用 json adapter.xmlHandler.ProcessXml(inputXml)    // 想用 xml 用 xml}

也能够重写函数:

type adapter struct {}

func (x *adapter) ProcessJson(json []byte) {// 自定义解决逻辑}

func (x *adapter) ProcessXml(xml string) {// 自定义解决逻辑}

func TestAdapterInGolang(t *testing.T) {inputJson := []byte("json_file") inputXml := "xml_file" // 原客户端
 handler := &jsonHandler{} handler.ProcessJson(inputJson)
 // 客户端接入适配器
 adapter := &adapter{&jsonHandler{}, &xmlHandler{}} adapter.ProcessJson(inputJson) // 想用 json 用 json adapter.ProcessXml(inputXml)    // 想用 xml 用 xml}

参考:

  1. https://refactoringguru.cn/design-patterns/adapter
  2. http://shusheng007.top/2021/09/08/018/
  3. https://www.runoob.com/design-pattern/adapter-pattern.html
  4. https://lailin.xyz/post/adapter.html#comments

正文完
 0