haiyux's blog

路漫漫其修远兮,吾将上下而求索


  • 首页

  • 归档

  • 关于我

  • 公益404

  • 搜索

行为模式

时间: 2022-05-12 分类: design mode   字数: 903 字 阅读: 2分钟 阅读次数:

责任链模式

责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。比如 kratos,gin等开源库的中间件实现。

代码实现

package main

import (
	"context"
	"fmt"
)

type Handler func(ctx context.Context, req interface{}) (resp interface{}, err error)

type Middleware func(next Handler) Handler

func Chain(middlewares ...Middleware) Middleware {
	return func(next Handler) Handler {
		for i := len(middlewares) - 1; i >= 0; i-- {
			next = middlewares[i](next)
		}
		return next
	}
}

func main() {
	c := Chain(func(next Handler) Handler {
		return func(ctx context.Context, req interface{}) (resp interface{}, err error) {
			fmt.Println("handler 1 before")
			resp, err = next(ctx, req)
			fmt.Println("handler 1 after")
			return resp, err
		}
	}, func(next Handler) Handler {
		return func(ctx context.Context, req interface{}) (resp interface{}, err error) {
			fmt.Println("handler 2 before")
			resp, err = next(ctx, req)
			fmt.Println("handler 2 after")
			return resp, err
		}
	})
	resp, err := c(func(ctx context.Context, req interface{}) (resp interface{}, err error) {
		fmt.Println("handler req:", req)
		return req, nil
	})(context.Background(), "hello")
	fmt.Println(resp, err)
}

/*
handler 1 before
handler 2 before
handler req: hello
handler 2 after
handler 1 after
hello <nil>
*/

观察者模式

观察者模式用于触发联动。一个对象的改变会触发其它观察者的相关动作,而此对象无需关心连动对象的具体实现。

代码实现

package main

import "fmt"

type subject interface {
	register(Observer observer)
	deregister(Observer observer)
	notifyAll()
}

type observer interface {
	update(string)
	getID() string
}

type item struct {
	observerList []observer
	name         string
	inStock      bool
}

func newItem(name string) *item {
	return &item{
		name: name,
	}
}
func (i *item) updateAvailability() {
	fmt.Printf("Item %s is now in stock\n", i.name)
	i.inStock = true
	i.notifyAll()
}
func (i *item) register(o observer) {
	i.observerList = append(i.observerList, o)
}

func (i *item) deregister(o observer) {
	i.observerList = removeFromslice(i.observerList, o)
}

func (i *item) notifyAll() {
	for _, observer := range i.observerList {
		observer.update(i.name)
	}
}

func removeFromslice(observerList []observer, observerToRemove observer) []observer {
	observerListLength := len(observerList)
	for i, observer := range observerList {
		if observerToRemove.getID() == observer.getID() {
			observerList[observerListLength-1], observerList[i] = observerList[i], observerList[observerListLength-1]
			return observerList[:observerListLength-1]
		}
	}
	return observerList
}

type customer struct {
	id string
}

func (c *customer) update(itemName string) {
	fmt.Printf("Sending email to customer %s for item %s\n", c.id, itemName)
}

func (c *customer) getID() string {
	return c.id
}

func main() {

	shirtItem := newItem("Nike Shirt")

	observerFirst := &customer{id: "abc@gmail.com"}
	observerSecond := &customer{id: "xyz@gmail.com"}

	shirtItem.register(observerFirst)
	shirtItem.register(observerSecond)

	shirtItem.updateAvailability()
}

/*
Item Nike Shirt is now in stock
Sending email to customer abc@gmail.com for item Nike Shirt
Sending email to customer xyz@gmail.com for item Nike Shirt
*/

模板方法模式

模版方法模式使用继承机制,把通用步骤和通用方法放到父类中,把具体实现延迟到子类中实现。使得实现符合开闭原则。

如实例代码中通用步骤在父类中实现(准备、下载、保存、收尾)下载和保存的具体实现留到子类中,并且提供 保存方法的默认实现。

因为Golang不提供继承机制,需要使用匿名组合模拟实现继承。

此处需要注意:因为父类需要调用子类方法,所以子类需要匿名组合父类的同时,父类需要持有子类的引用。

代码实现

package main

import "fmt"

type Downloader interface {
	Download(uri string)
}

type template struct {
	implement
	uri string
}

type implement interface {
	download()
	save()
}

func newTemplate(impl implement) *template {
	return &template{
		implement: impl,
	}
}

func (t *template) Download(uri string) {
	t.uri = uri
	fmt.Print("prepare downloading\n")
	t.implement.download()
	t.implement.save()
	fmt.Print("finish downloading\n")
}

func (t *template) save() {
	fmt.Print("default save\n")
}

type HTTPDownloader struct {
	*template
}

func NewHTTPDownloader() Downloader {
	downloader := &HTTPDownloader{}
	template := newTemplate(downloader)
	downloader.template = template
	return downloader
}

func (d *HTTPDownloader) download() {
	fmt.Printf("download %s via http\n", d.uri)
}

func (*HTTPDownloader) save() {
	fmt.Printf("http save\n")
}

type FTPDownloader struct {
	*template
}

func NewFTPDownloader() Downloader {
	downloader := &FTPDownloader{}
	template := newTemplate(downloader)
	downloader.template = template
	return downloader
}

func (d *FTPDownloader) download() {
	fmt.Printf("download %s via ftp\n", d.uri)
}

func main() {
	downloader := NewHTTPDownloader()
	downloader.Download("http://example.com/abc.zip")

	downloader = NewFTPDownloader()
	downloader.Download("ftp://example.com/abc.zip")
}

/*
prepare downloading
download http://example.com/abc.zip via http
http save
finish downloading
prepare downloading
download ftp://example.com/abc.zip via ftp
default save
finish downloading
*/

命令模式

#设计模式#
QQ扫一扫交流

标题:行为模式

链接:https://www.zhaohaiyu.com/post/designmode/behavioral/

作者:haiyux

声明: 本博客文章除特别声明外,均采用 CC BY-NC-SA 3.0许可协议,转载请注明出处!

创作实属不易,如有帮助,那就打赏博主些许茶钱吧 ^_^
WeChat Pay

微信打赏

Alipay

支付宝打赏

结构型模式
  • 文章目录
  • 站点概览
haiyux

haiyux

路漫漫其修远兮,吾将上下而求索

62 日志
8 分类
20 标签
GitHub Email
友情链接
  • kratos
  • farer
  • 我的博客园
  • 李文周
  • 凡梦星尘
标签云
  • Golang 30
  • 微服务 8
  • Mysql 7
  • HTTP 4
  • Protobuf 4
  • 运维 4
  • Grpc 3
  • 设计模式 3
  • Redis 2
  • Ddd 1
  • Docker 1
  • Kratos 1
  • Makefile 1
  • Mq 1
  • Nginx 1
  • Raft 1
  • Thrift 1
  • Traceing 1
  • Wire 1
  • 泛型 1
  • 责任链模式
    • 代码实现
  • 观察者模式
    • 代码实现
  • 模板方法模式
    • 代码实现
  • 命令模式
© 2010 - 2022 haiyux's blog
Powered by - Hugo v0.98.0 / Theme by - NexT
Storage by 又拍云存储 / 京ICP备19052634号-2
0%