Go语言设计模式

Posted double-w

tags:

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

 

Proxy Pattern 代理模式

The proxy pattern provides an object that controls access to another object, intercepting all calls. 代理模式提供一个对象,该对象控制对另一个对象的访问,拦截所有调用。
The proxy could interface to anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate. Short idea of implementation。代理可以连接到任何东西:网络连接、内存中的大型对象、文件或其他一些昂贵或无法复制的资源。简短的实施思路:
package main

import (
	"fmt"
	"time"
)

// To use proxy and to object they must implement same methods
type IObject interface {
	ObjDo(action string)
}

// Object represents real objects which proxy will delegate data
type Object struct {
	action string // Action behavior
}

// ProxyObject represents proxy object with intercepts actions
func (obj *Object) ObjDo(action string) {
	fmt.Printf("I can %s", action)
}

// ProxyObject represents proxy object with intercepts actions
type ProxyObject struct {
	object *Object
}

// ObjDo are implemented IObject and intercept action before send in real Object
func (p *ProxyObject) ObjDo(action string) {
	if p.object == nil {
		p.object = new(Object)
	}
	if action == "work1" {
		p.object.ObjDo(action)
	}
}

func main() {
	proxy := ProxyObject{object:nil}
	proxy.ObjDo("work1")
	time.Sleep(1*time.Second)
}

  

Observer Pattern 观察者模式

The observer pattern allows a type instance to "publish" events to other type instances ("observers") who wish to be updated when a particular event occurs. 观察者模式允许类型实例“发布”事件到其他类型实例(“观察者”),这些实例希望在特定事件发生时被更新。

In long-running applications—such as webservers—instances can keep a collection of observers that will receive notification of triggered events. Implementations vary, but interfaces can be used to make standard observers and notifiers。在长期运行的应用程序(如webservers)中,实例可以保存一个观察者集合,该集合将接收触发事件的通知。实现方法各不相同,但是接口可以用来创建标准的观察者和通知程序:

观察者模式包含如下角色:
  1.目标(Subject): 目标知道它的观察者。可以有任意多个观察者观察同一个目标。 提供注册和删除观察者对象的接口。
  2.具体目标(ConcreteSubject):  将有关状态存入各ConcreteObserver对象。
  3. 观察者(Observer):  为那些在目标发生改变时需获得通知的对象定义一个更新接口。当它的状态发生改变时, 向它的各个观察者发出通知。

  4. 具体观察者(ConcreteObserver):   维护一个指向ConcreteSubject对象的引用。存储有关状态,这些状态应与目标的状态保持一致。实现O b s e r v e r的更新接口以使自身状态与目标的状态保持一致。

package main

import (
	"container/list"
	"fmt"
)

type Subject interface {
	Attach(Observer)  // 注册观察者
	Detach(Observer)  // 释放观察者
	Notify()  // 通知所有注册的观察者
}

type Observer interface {
	Update(Subject)  // 观察者进行更新状态
}

type ConcreteSubject struct {
	observers *list.List
	value int
}

func NewConcreteSubject() *ConcreteSubject {  // 返回一个被观察者
	s := new(ConcreteSubject)
	s.observers = list.New()
	return s
}

func (s *ConcreteSubject) Attach(observer Observer) {  //注册观察者
	s.observers.PushBack(observer)
}

func (s *ConcreteSubject) Detach(observer Observer) {   // 释放观察者,类似于链路循环
	for ob := s.observers.Front(); ob != nil; ob = ob.Next() {
		if ob.Value.(*Observer) == &observer {
			s.observers.Remove(ob)
			break
		}
	}
}

func (s *ConcreteSubject) Notify() { // 通知所有观察者
	for ob := s.observers.Front(); ob != nil; ob = ob.Next() {
		ob.Value.(Observer).Update(s)
	}
}

func (s *ConcreteSubject) setValue(value int) {  // 设置属性值
	s.value = value
	s.Notify()
}

func (s *ConcreteSubject) getValue() int {
	return s.value  // 获取值
}

/**
 * 具体观察者 implements Observer
 *
 */
type ConcreteObserver1 struct {
}

func (c *ConcreteObserver1) Update(subject Subject) {
	println("ConcreteObserver1  value is ", subject.(*ConcreteSubject).getValue())  //监视被监视着的状态
}

/**
 * 具体观察者 implements Observer
 *
 */
type ConcreteObserver2 struct {
}

func (c *ConcreteObserver2) Update(subject Subject) {
	fmt.Println(subject.(*ConcreteSubject))
	println("ConcreteObserver2 value is ", subject.(*ConcreteSubject).getValue())
}

func main() {
	subject := NewConcreteSubject()
	// 只要实现了Update函数的,满足Object接口的结构体都是可以进行注册的
	observer1 := new(ConcreteObserver1)
	observer2 := new(ConcreteObserver2)
	subject.Attach(observer1)
	subject.Attach(observer2)
	subject.setValue(5)
}

/*
&{0xc00006c360 5}
ConcreteObserver1  value is  5
ConcreteObserver2 value is  5*/

  

 

以上是关于Go语言设计模式的主要内容,如果未能解决你的问题,请参考以下文章

[Go] 并发和并行的区别

Go 语言也 10 岁了!这里或许有你不知道的 Go 的成长历程

一天一门编程语言设计一套Go语言中的 Stream API 接口代码实现

编程模式之Go语言如何实现装饰器

GoLand:Go编码开发工具|Go语言编码协助人体工学设计快速导航代码生成

go语言设计初衷和优势