首页 > 其他分享 >结构型模式

结构型模式

时间:2023-06-26 23:25:33浏览次数:38  
标签:return string fmt 模式 func error type 结构型

适配器模式

适配器模式用于转换一种接口适配另一种接口。比如,现在有个借口是对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

https://refactoringguru.cn/design-patterns

https://lailin.xyz/post/singleton.html

标签:return,string,fmt,模式,func,error,type,结构型
From: https://www.cnblogs.com/haiyux/p/17507415.html

相关文章

  • 结构型模式概述
    结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。......
  • 桥接模式
    目录1.概述2.结构3.案例4.使用场景1.概述现在有一个需求,需要创建不同的图形,并且每个图形都有可能会有不同的颜色。我们可以利用继承的方式来设计类的关系:我们可以发现有很多的类,假如我们再增加一个形状或再增加一种颜色,就需要创建更多的类。试想,在一个有多种可能会变化......
  • 组合模式详解
    简介组合模式(Composite)是针对由多个节点对象(部分)组成的树形结构的对象(整体)而发展出的一种结构型设计模式,它能够使客户端在操作整体对象或者其下的每个节点对象时做出统一的响应,保证树形结构对象使用方法的一致性,使客户端不必关注对象的整体或部分,最终达到对象复杂的层次结构与......
  • F5APM第七期Network Access模式配置
    F5APM第七期NetworkAccess模式配置’......
  • F5APM第六期Portal Access模式配置
    F5APM第六期PortalAccess模式配置Portal_conn......
  • 一文掌握设计模式(定义+UML类图+应用)
    一、引子从学编程一开始就被告知,要想做一名优秀的程序员两大必要技能:1.源码阅读(JDK、C等底层语言封装)2.设计模式(使用某种语言优雅的落地典型场景功能)。一般随着工作年限的增长,被迫对底层语言/框架源码阅读的越来愈多,但是设计模式如不刻意去学习,永远不会真正掌握。笔者把设计......
  • 结构型模式-静态代理模式
    #模式类型:结构性模型#模型方法:静态代理模式#作用:在不修改目标代码的情况下,可以控制目标代码的访问,可以在其前后添加自己的业务代码#使用场景:监控。日志,限流fromabcimportABCMeta,abstractmethodclassITeacher(metaclass=ABCMeta):"""教师接口"""@abs......
  • epoll的两种触发模式
    epoll有两种模式,EdgeTriggered(简称ET)和LevelTriggered(简称LT).在采用这两种模式时要注意的是,如果采用ET模式,那么仅当状态发生变化时才会通知,而采用LT模式类似于原来的select/poll操作,只要还有没有处理的事件就会一直通知. 以代码来说明问题: 首先给出server的代......
  • java使用AES算法的CBC模式加密
    https://blog.csdn.net/qq_25816185/article/details/81626499?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-81626499-blog-121345545.235%5Ev38%5Epc_relevant_sort&depth_1-utm_source=distribute......
  • redis 主从复制如何实现的? redis 的集群模式如何实现? redis 的 key 是如何寻址的?
    1.redis主从复制如何实现的?1.1 连接建立阶段1.2  数据同步阶段1.3命令传播阶段是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。需要注意,主从复制的开启,完全是在从节点发起的;不需......