6

Go设计模式:composite模式

 3 years ago
source link: https://jiajunhuang.com/articles/2020_07_02-go_design_pattern_composite.md.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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模式可以用于递归的表示某些东西的情况下,比如文件系统、窗口系统 等大量共同属性、操作的情况下。



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

读《投资中最简单的事》

后端工程师学前端(三): CSS进阶(特指度、单位和字体族)

后端工程师学前端(二): CSS基础知识(规则与选择器)

Swift语法笔记

后端工程师学前端(一): HTML

读《管理的实践》

frp 源码阅读与分析(二):TCP内网穿透的实现

五天不用微信 - 爽得很

frp 源码阅读与分析(一):流程和概念

学习frp源码之简洁的在两个connection之间转发流量

自己动手写一个反向代理

读《债务危机》

从XMonad迁移到i3

socks5 协议详解

服务器IP被ban学到的经验




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK