[07]Go设计模式:过滤器模式(FilterPattern)

Posted 0pandas0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[07]Go设计模式:过滤器模式(FilterPattern)相关的知识,希望对你有一定的参考价值。

过滤器模式

一、简介

过滤器模式(Filter Pattern)或标准模式(Criteria Pattern)是一种设计模式,这种模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。

二、代码

package main

import (
    "errors"
    "fmt"
    "log"
    "strconv"
    "strings"
)

// Request is the input of the filter
type Request interface{}

// Response is the output of the filter
type Response interface{}

// Filter interface is the definition of the data processing components
// Pipe-Filter structure
type Filter interface {
    Process(data Request) (Response, error)
}

type SplitFilter struct {
    delimiter string
}

func NewSplitFilter(delimiter string) *SplitFilter {
    return &SplitFilter{delimiter}
}

func (sf *SplitFilter) Process(data Request) (Response, error) {
    str, ok := data.(string) //检查数据格式/类型,是否可以处理
    if !ok {
        return nil, fmt.Errorf("input data must be string")
    }
    parts := strings.Split(str, sf.delimiter)
    return parts, nil
}


type ToIntFilter struct {
}

func NewToIntFilter() *ToIntFilter {
    return &ToIntFilter{}
}

func (tif *ToIntFilter) Process(data Request) (Response, error) {
    parts, ok := data.([]string)
    if !ok {
        return nil, fmt.Errorf("input data should be []string")
    }
    ret := make([]int, 0)
    for _, part := range parts {
        s, err := strconv.Atoi(part)
        if err != nil {
            return nil, err
        }
        ret = append(ret, s)
    }
    return ret, nil
}

type SumFilter struct {
}

func NewSumFilter() *SumFilter {
    return &SumFilter{}
}

func (sf *SumFilter) Process(data Request) (Response, error) {
    elms, ok := data.([]int)
    if !ok {
        return nil, errors.New("input data should be []int")
    }
    ret := 0
    for _, elem := range elms {
        ret += elem
    }
    return ret, nil
}

type Pipeline struct {
    Name    string
    Filters *[]Filter
}

func NewPipeline(name string, filters ...Filter) *Pipeline {
    return &Pipeline{
        Name:    name,
        Filters: &filters,
    }
}

// call each filter's process function
func (p *Pipeline) Process(data Request) (Response, error) {
    var ret interface{}
    var err error
    for _, filter := range *p.Filters {
        ret, err = filter.Process(data)
        if err != nil {
            return ret, err
        }
        data = ret
    }
    return ret, err
}


func main() {
    //例子中将字符串分割,再转成int,再求和
    split := NewSplitFilter(",")
    converter :=NewToIntFilter()
    sum := NewSumFilter()
    p :=NewPipeline("p1", split, converter, sum)
    ret, err := p.Process("4,5,6")
    if err != nil {
        log.Fatal(err)
    }
    if ret != 15 {
        log.Fatalf("The expected is 6, but the actual is %d", ret)
    }
    fmt.Println(ret)
}

完整代码:https://gitee.com/ncuzhangben/GoStudy/tree/master/go-design-pattern/07-Filter

三、参考链接

1、https://www.runoob.com/design-pattern/filter-pattern.html

以上是关于[07]Go设计模式:过滤器模式(FilterPattern)的主要内容,如果未能解决你的问题,请参考以下文章

Go设计模式大全 | Gopher Daily (2020.09.07) ʕ◔ϖ◔ʔ

Go 单例模式[个人翻译]

如果 URL 与 Go 中的任何模式都不匹配,如何提供文件?

mongodb过滤器和仅项目具有所提供模式的最大id的文档

使用 NSPredicate 过滤 NSFileManger 内容以获取文件“模式”列表

07-02 基于协同过滤的推荐算法