Go的常用设计模式

Go的常用设计模式,第1张

好记性不如烂笔头,学习编程的最好方式就是自己把代码动手敲一遍

1.策略模式(strategy)

在实际应用中, 我们对不同的场景要采取不同的应对措施,也就是不同的策略。定义一个接口,传入的不同对象实现了接口,因此自动调用对应的策略
其中strategy.go:

package strategy

import "fmt"

type Payment struct {
	payctx   *PayCtx
	strategy Strategy
}

type Strategy interface {
	Pay(*PayCtx)
}

type PayCtx struct {
	money int
	name  string
}

func NewPayment(money int, name string, strategy Strategy) *Payment {
	return &Payment{
		payctx: &PayCtx{
			money: money,
			name:  name,
		},
		strategy: strategy,
	}
}

func (p *Payment) Pay() {
	p.strategy.Pay(p.payctx)
}

type Cash struct{}

func (cash *Cash) Pay(ctx *PayCtx) {
	fmt.Printf("%s使用现金支付了%d\n", ctx.name, ctx.money)
}

type Bank struct{}

func (bank *Bank) Pay(ctx *PayCtx) {
	fmt.Printf("%s使用银行支付了%d\n", ctx.name, ctx.money)
}

测试代码strategy_test.go:

package strategy

import "testing"

func TestNewPayment(t *testing.T) {
	a := NewPayment(18, "zr", &Cash{})
	b := NewPayment(9090, "sys", &Bank{})

	a.Pay()
	b.Pay()
}
单例模式(singleton)

许多时候软件内只需要一个实例对象,此时便可用单例模式创建此对象;
单例模式算是go中实现最简单的了:

package singleton

import "sync"

var s *Singleton
var once sync.Once

type Singleton struct{}

func GetSingleton() *Singleton {
	once.Do(func() {
		s = &Singleton{}
	})

	return s
}

测试singleton_test.go

package singleton

import (
	"sync"
	"testing"
)

func TestGetSingleton(t *testing.T) {
	var wg sync.WaitGroup
	wg.Add(1000)
	start := make(chan struct{})
	arr := make([]*Singleton, 1000)
	for i := 0; i < 1000; i++ {
		//同时起1000个goroutine
		go func(index int) {
			<-start 					// 全部阻塞在此
			singleton := GetSingleton() // 获取单例对象
			arr[index] = singleton
			wg.Done() // 将每个goroutine获得的单例对象存储到数组
		}(i)
	}
	close(start) // 关闭通道的同时,1000个goroutine同时执行
	wg.Wait()    // 阻塞等待所有goroutine执行完成

	for i := 0; i < 999; i++ {
		if arr[i] != arr[i+1] {
			t.Fatalf("同时有多个实例")
		}
	}
}
简单工厂模式(simple_factory)

当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。

package simple_factory

type Production interface {
	create() string
}

type Factory struct{}

func (f *Factory) NewProduction(name int) Production {
	switch name {
	case 1:
		return &Product1{}
	case 2:
		return &Product2{}
	default:
		return nil
	}
}

type Product1 struct{}

func (p Product1) create() string {
	return "产品1"
}

type Product2 struct{}

func (p Product2) create() string {
	return "产品2"
}

测试代码simeple_factory_test.go

package simple_factory

import (
	"testing"
)

func TestFactory_NewProduction(t *testing.T) {
	factory := Factory{}
	production1 := factory.NewProduction(1)
	production2 := factory.NewProduction(2)

	if production1.create() != "产品1" {
		t.Fatalf("产品1测试失败")
	}

	if production2.create() != "产品2" {
		t.Fatalf("产品2测试失败")
	}

}
观察者模式

观察者模式用于触发联动。

subject的改变会触发他所有观察者的相关动作

package observer

import "fmt"

type IObserver interface {
	Notify()
}

type ISubject interface {
	AddObserver(observer ...IObserver)
	NotifyObserver()
}

type Observer struct{}

type Subject struct {
	OArr []IObserver
}

func NewObserver() *Observer {
	return &Observer{}
}

func NewSubject() *Subject {
	return &Subject{}
}

func (o *Observer) Notify() {
	fmt.Println("执行命令")
}

func (s *Subject) AddObserver(observer ...IObserver) {
	s.OArr = append(s.OArr, observer...)
}

func (s *Subject) NotifyObserver() {
	for _, v := range s.OArr {
		v.Notify()
	}
}

测试代码observer_test.go:

package observer

import "testing"

func TestObserver_Notify(t *testing.T) {
	observer := NewObserver()
	subject := NewSubject()
	subject.AddObserver(observer)
	subject.NotifyObserver()
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/996212.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存