结构型模式
作者:@daemon365
本文为作者原创,转载请注明出处:https://www.cnblogs.com/daemon365/p/17507415.html
适配器模式
适配器模式用于转换一种接口适配另一种接口。比如,现在有个借口是对json
字符串进行分析等,现在有一些yaml
文件也要分析,这时候我我们就应该给yaml
字符串就个适配器,转换成json
字符串,然后就行分析。
代码实现
package main import ( "fmt" "github.com/ghodss/yaml" ) type Analysis interface { Analyze(string) error } type JsonAnalysis struct{} func (*JsonAnalysis) Analyze(jsonStr string) error { // 函数逻辑 fmt.Println(jsonStr) return nil } type yamlAnalysis struct { ja *JsonAnalysis } func (y *yamlAnalysis) Analyze(yamlStr string) error { bs, err := yaml.YAMLToJSON([]byte(yamlStr)) if err != nil { return err } return y.ja.Analyze(string(bs)) } func main() { ja := &JsonAnalysis{} err := ja.Analyze("{\"name\":\"zhy\",\"age\":18}") if err != nil { fmt.Println(err) } ya := &yamlAnalysis{ja: ja} err = ya.Analyze("name: you\nage: 88") if err != nil { fmt.Println(err) } } /* {"name":"zhy","age":18} {"age":88,"name":"you"} */
桥接模式
桥接模式分离抽象部分和实现部分。使得两部分独立扩展。
桥接模式类似于策略模式,区别在于策略模式封装一系列算法使得算法可以互相替换。
策略模式使抽象部分和实现部分分离,可以独立变化。
比如要发消息,可以发很多种方式,微信、qq、email、短信等等,也可以发很多类型,日常、紧急等的。这时我们可以把发送的的方法做抽象,把类型做实现。
代码实现
package main import "fmt" type Message interface { SendMessage(s string) error } type MessageMethod interface { Send(string) error } type qq struct{} func (*qq) Send(s string) error { fmt.Println("send qq:", s) return nil } type weixin struct{} func (*weixin) Send(s string) error { fmt.Println("send weixin:", s) return nil } type email struct{} func (*email) Send(s string) error { fmt.Println("send email:", s) return nil } type InfoMessage struct { method MessageMethod } func (i *InfoMessage) SendMessage(s string) error { s = "info message: " + s return i.method.Send(s) } type UrgencyMessage struct { method MessageMethod } func (u *UrgencyMessage) SendMessage(s string) error { s = "urgency message: " + s return u.method.Send(s) } func main() { qq := new(qq) weixin := new(weixin) email := new(email) info := new(InfoMessage) info.method = qq info.SendMessage("hello") info.method = weixin info.SendMessage("hello") info.method = email info.SendMessage("hello") urgency := new(UrgencyMessage) urgency.method = qq urgency.SendMessage("hello") urgency.method = weixin urgency.SendMessage("hello") urgency.method = email urgency.SendMessage("hello") } /* send qq: info message: hello send weixin: info message: hello send email: info message: hello send qq: urgency message: hello send weixin: urgency message: hello send email: urgency message: hello */
装饰器模式
装饰模式使用对象组合的方式动态改变或增加对象行为。Go语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式。使用匿名组合,在装饰器中不必显式定义转调原对象方法。
代码实现
package main import "fmt" type Component interface { Calc() int } type ConcreteComponent struct{} func (*ConcreteComponent) Calc() int { return 10 } type MulDecorator struct { Component num int } func WarpMulDecorator(c Component, num int) Component { return &MulDecorator{ Component: c, num: num, } } func (d *MulDecorator) Calc() int { return d.Component.Calc() * d.num } type AddDecorator struct { Component num int } func WarpAddDecorator(c Component, num int) Component { return &AddDecorator{ Component: c, num: num, } } func (d *AddDecorator) Calc() int { return d.Component.Calc() + d.num } func main() { c := &ConcreteComponent{} md := WarpMulDecorator(c, 2) ad := WarpAddDecorator(c, 3) fmt.Println(md.Calc()) fmt.Println(ad.Calc()) } /* 20 13 */
代理模式
代理模式用于延迟处理操作或者在进行实际操作前后进行其它处理。比如在限流中间件中
代码实现
package main import ( "errors" "fmt" "sync" "time" ) type Serve interface { handle(name string) (string, error) } type server struct { lock sync.RWMutex serve Serve maxAllowedRequest int rateLimiter map[string]int } func (s *server) getService(name string) (string, error) { s.lock.RLock() nowNumber := s.rateLimiter[name] s.lock.RUnlock() if nowNumber >= s.maxAllowedRequest { return "", errors.New("rate limit") } // 更新计数器 s.lock.Lock() s.rateLimiter[name]++ s.lock.Unlock() str, err := s.serve.handle(name) // 执行后减少计数器 s.lock.Lock() s.rateLimiter[name]-- s.lock.Unlock() if err != nil { return "", err } return str, nil } type hand struct{} func (h *hand) handle(name string) (string, error) { time.Sleep(time.Microsecond * 500) return fmt.Sprintf("hello %s", name), nil } func main() { wg := &sync.WaitGroup{} wg.Add(20) s := &server{ serve: &hand{}, maxAllowedRequest: 10, rateLimiter: map[string]int{}, } for i := 0; i < 20; i++ { go func(i int) { defer wg.Done() res, err := s.getService("world") if err != nil { fmt.Println(i, "error:", err) } else { fmt.Println(i, "success:", res) } }(i) } wg.Wait() } /* 15 error: rate limit 18 error: rate limit 10 error: rate limit 4 error: rate limit 7 error: rate limit 6 error: rate limit 16 error: rate limit 9 error: rate limit 11 error: rate limit 17 error: rate limit 14 success: hello world 19 success: hello world 13 success: hello world 2 success: hello world 12 success: hello world 1 success: hello world 3 success: hello world 8 success: hello world 5 success: hello world 0 success: hello world */
组合模式
组合模式统一对象和对象集,使得使用相同接口使用对象和对象集。
组合模式常用于树状结构,用于统一叶子节点和树节点的访问,并且可以用于应用某一操作到所有子节点。
比如要搜索文件夹下的所有文件名
代码实现
package main import "fmt" type component interface { search(string) } type file struct { name string } func (f *file) search(keyword string) { fmt.Printf("Searching for keyword %s in file %s\n", keyword, f.name) } func (f *file) getName() string { return f.name } type folder struct { components []component name string } func (f *folder) search(keyword string) { fmt.Printf("Serching recursively for keyword %s in folder %s\n", keyword, f.name) for _, composite := range f.components { composite.search(keyword) } } func (f *folder) add(c component) { f.components = append(f.components, c) } func main() { file1 := &file{name: "File1"} file2 := &file{name: "File2"} file3 := &file{name: "File3"} folder1 := &folder{ name: "Folder1", } folder1.add(file1) folder2 := &folder{ name: "Folder2", } folder2.add(file2) folder2.add(file3) folder2.add(folder1) folder2.search("rose") } /* Serching recursively for keyword rose in folder Folder2 Searching for keyword rose in file File2 Searching for keyword rose in file File3 Serching recursively for keyword rose in folder Folder1 Searching for keyword rose in file File1 */
外观模式
API 为facade 模块的外观接口,大部分代码使用此接口简化对facade类的访问。
facade模块同时暴露了a和b 两个Module 的NewXXX和interface,其它代码如果需要使用细节功能时可以直接调用。
代码实现
package main import "fmt" func NewAPI() API { return &apiImpl{ a: NewAModuleAPI(), b: NewBModuleAPI(), } } //API is facade interface of facade package type API interface { Test() string } //facade implement type apiImpl struct { a AModuleAPI b BModuleAPI } func (a *apiImpl) Test() string { aRet := a.a.TestA() bRet := a.b.TestB() return fmt.Sprintf("%s\n%s", aRet, bRet) } //NewAModuleAPI return new AModuleAPI func NewAModuleAPI() AModuleAPI { return &aModuleImpl{} } //AModuleAPI ... type AModuleAPI interface { TestA() string } type aModuleImpl struct{} func (*aModuleImpl) TestA() string { return "A module running" } //NewBModuleAPI return new BModuleAPI func NewBModuleAPI() BModuleAPI { return &bModuleImpl{} } //BModuleAPI ... type BModuleAPI interface { TestB() string } type bModuleImpl struct{} func (*bModuleImpl) TestB() string { return "B module running" } func main() { api := NewAPI() fmt.Println(api.Test()) } /* A module running B module running */
享元模式
享元模式从对象中剥离出不发生改变且多个实例需要的重复数据,独立出一个享元,使多个对象共享,从而节省内存以及减少对象数量。
代码实现
package main import "fmt" type ImageFlyweightFactory struct { maps map[string]*ImageFlyweight } var imageFactory *ImageFlyweightFactory func GetImageFlyweightFactory() *ImageFlyweightFactory { if imageFactory == nil { imageFactory = &ImageFlyweightFactory{ maps: make(map[string]*ImageFlyweight), } } return imageFactory } func (f *ImageFlyweightFactory) Get(filename string) *ImageFlyweight { image := f.maps[filename] if image == nil { image = NewImageFlyweight(filename) f.maps[filename] = image } return image } type ImageFlyweight struct { data string } func NewImageFlyweight(filename string) *ImageFlyweight { // Load image file data := fmt.Sprintf("image data %s", filename) return &ImageFlyweight{ data: data, } } func (i *ImageFlyweight) Data() string { return i.data } type ImageViewer struct { *ImageFlyweight } func NewImageViewer(filename string) *ImageViewer { image := GetImageFlyweightFactory().Get(filename) return &ImageViewer{ ImageFlyweight: image, } } func (i *ImageViewer) Display() { fmt.Printf("Display: %s\n", i.Data()) }
References
https://github.com/senghoo/golang-design-pattern
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?