Go设计模式:composite模式

典型的composite模式,是这样的,对于多个对象,由于我们只需要其中一部分共同的操作,因此我们可以通过定义一个父类,来规定 我们所需要的操作,却并不管具体每个子类到底是什么样的。看下维基百科的定义:

The composite pattern describes a group of objects that are treated the same way as a single instance
of the same type of object. The intent of a composite is to "compose" objects into tree structures to
represent part-whole hierarchies. Implementing the composite pattern lets clients treat individual
objects and compositions uniformly.

这里说明了几个问题:

  • 我们会把一组对象当作同样地类型,也就是说,我们并不在乎它是什么类的实例,我们只在乎有什么操作
  • 通常会用树状结构来表示,对应到编程语言,其实就是使用继承的方式

我们来看Python的例子,仍然以发短信为例子:

import abc


class SMSSender:
    @abc.abstractmethod
    def send(self, user, message):
        raise NotImplementedError()


class AliyunSender(SMSSender):
    def send(self, user, message):
        print("使用aliyun向{}发送信息{}")

    def report(self):
        print("blabla")


class TencentSender(SMSSender):
    def send(self, user, message):
        print("使用tencent向{}发送信息{}")

    def shutdown(self):
        print("shutdown")

瞧,AliyunSender和TencentSender分别继承了SMSSender,他们都实现了 send 方法,而且他们还各自都有自己的不同的子类方法, 但是我们使用的时候并不在乎,因为我们只关心是否实现了 send 方法。

诶?等等,我们这不是讲的Go的设计模式吗?我们来看下Go语言里面如何实现。通常我们有两种方式,一种其实就是上面的翻版:

package main

import (
	"fmt"
)

type Sender struct{}

func (s *Sender) Send(user, message string) {
	panic("not implemented")
}

type AliyunSender struct {
	Sender
}

func (a *AliyunSender) Send(user, message string) {
	fmt.Printf("使用aliyun向%s发送信息%s\n", user, message)
}

type TencentSender struct {
	Sender
}

func (t *TencentSender) Send(user, message string) {
	fmt.Printf("使用aliyun向%s发送信息%s\n", user, message)
}

但是这在Go语言里,并不是最优解,更多的,我们会使用接口。

package main

import (
	"fmt"
)

type Sender interface {
	Send(user, message string)
}

type AliyunSender struct {
	Sender
}

func (a *AliyunSender) Send(user, message string) {
	fmt.Printf("使用aliyun向%s发送信息%s\n", user, message)
}

type TencentSender struct {
	Sender
}

func (t *TencentSender) Send(user, message string) {
	fmt.Printf("使用aliyun向%s发送信息%s\n", user, message)
}

var (
	_ Sender = &AliyunSender{}
	_ Sender = &TencentSender{}
)

composite 的核心并不是一定要用树状模式(也就是对应编程语言继承)来表示,而是说我们只关心是否实现了接口,并不关心它具体是啥。 这不就是Go里面接口的用法么?

这就是Composite模式在Go语言里的应用。实际项目中,composite模式可以用于递归的表示某些东西的情况下,比如文件系统、窗口系统 等大量共同属性、操作的情况下。


ref:


微信公众号
关注公众号,获得及时更新

更多文章
  • 好的命名是最好的文档
  • 读《系统之美:决策者的系统思考》
  • Linux高分屏支持
  • GCC默认的头文件搜索路径
  • 读《远见-如何规划职业生涯3大阶段》
  • 后端工程师学前端(五): SASS
  • 后端工程师学前端(四): CSS进阶(盒子模型)
  • 读《投资中最简单的事》
  • 后端工程师学前端(三): CSS进阶(特指度、单位和字体族)
  • 后端工程师学前端(二): CSS基础知识(规则与选择器)
  • Swift语法笔记
  • 后端工程师学前端(一): HTML
  • 读《管理的实践》
  • frp 源码阅读与分析(二):TCP内网穿透的实现
  • 五天不用微信 - 爽得很