golang

Go 实现责任链模式

2021-12-19  本文已影响0人  三梦哥
package main

import (
    "context"
    "errors"
    "fmt"
    "log"
    "net/http"
)

type Request struct {
    Data   string
    Name   string
    Upload string
}

type Response struct {
}

type Context struct {
    Req      *Request
    Resp     *Response
    handlers []FilterFunc
    index    int
}

func (c *Context) Next() error {
    c.index++
    s := len(c.handlers)
    for ; c.index <= s; c.index++ {
        if err := c.handlers[c.index-1](c); err != nil {
            return err
        }
    }
    return nil
}

type Filter interface {
    Handle(ctx *Context) error
}

type FilterFunc func(ctx *Context) error

type FilterDecorator struct {
    filters []FilterFunc
}

func NewFilterDecorator() *FilterDecorator {
    return &FilterDecorator{}
}

func (d *FilterDecorator) Use(middlewares ...FilterFunc) {
    d.filters = append(d.filters, middlewares...)
}

func (d *FilterDecorator) Do(request *Request, response *Response) error {
    c := new(Context)
    c.Req = request
    c.Resp = response
    c.handlers = d.filters
    return c.Next()
}

func ValidateParam() FilterFunc {
    return func(ctx *Context) error {
        req := ctx.Req
        if req.Name != "Tom" {
            return errors.New("name is not Tom")
        }
        ctx.Next()
        return nil
    }
}

func ProcessFilter() FilterFunc {
    return func(ctx *Context) (err error) {
        log.Println("processing ProcessFilter")
        defer func() {
            log.Println("after ProcessFilter")
        }()
        ctx.Req.Name = "Jack"
        if err := ctx.Next(); err != nil {
            return err
        }
        return nil
    }
}

type Uploader interface {
    Upload(ctx context.Context, data string) error
}

type UploaderFunc func(ctx context.Context, data string) error

func (u UploaderFunc) Upload(ctx context.Context, data string) error {
    return u(ctx, data)
}

type AliyunClient struct {
    c *http.Client
}

func NewAliyunClient() *AliyunClient {
    return &AliyunClient{}
}

func (a *AliyunClient) Upload(ctx context.Context, data string) error {
    log.Printf("AliyunClient Upload:%s", data)
    return nil
}

type AwsClient struct {
    c *http.Client
}

func NewAwsClient() *AwsClient {
    return &AwsClient{}
}

func (a *AwsClient) Upload(ctx context.Context, data string) error {
    log.Printf("AwsClient Upload:%s", data)
    return nil
}

func AzureUpload() UploaderFunc {
    return func(ctx context.Context, data string) error {
        log.Printf("AzureClient Upload:%s", data)
        return nil
    }

}

func UploadFilter() FilterFunc {
    aliyun := NewAliyunClient()
    aws := NewAwsClient()
    uploaderMap := map[string]Uploader{
        "aliyun": aliyun,
        "aws":    aws,
        "azure":  AzureUpload(),
    }
    log.Println("--Hello World")
    return func(ctx *Context) (err error) {
        log.Println("processing UploadFilter")
        fmt.Printf("Name:%s\n", ctx.Req.Name)
        var uploader Uploader
        uploader, ok := uploaderMap[ctx.Req.Upload]
        if !ok {
            uploader = aliyun
        }
        if err = uploader.Upload(context.Background(), ctx.Req.Data); err != nil {
            return
        }
        if err := ctx.Next(); err != nil {
            return err
        }
        return nil
    }
}

func main() {
    d := NewFilterDecorator()
    d.Use(ValidateParam())
    d.Use(ProcessFilter())
    d.Use(UploadFilter())
    req := new(Request)
    req.Data = "Hello World"
    req.Upload = "azure"
    resp := new(Response)
    if err := d.Do(req, resp); err != nil {
        log.Println(err)
    }
}

上一篇 下一篇

猜你喜欢

热点阅读