談起消息隊列,內心還是會有些波瀾。 消息隊列、緩存、分庫分表是高併發解決方案三劍客,而消息隊列是我最喜歡,也是思考最多的技術。我想按照下麵的四個階段分享我與消息隊列的故事,同時也是對我技術成長經歷的回顧。 ...
責任鏈模式
組成:由多個處理器及處理器處理標誌串聯組成
作用:常用於處理流水線事務,利用多個處理器對同一個對象進行處理,可以利用各處理器開關
場景:常見邏輯層處理邏輯:獲取參數、fetch數據、邏輯處理數據、返回參數一系列數據處理
優點:將複雜的流水線處理邏輯簡化為一個個單元,操作較為便捷,可以隨意在處理器之間串聯穿插新處理器
package burden_chain
import "fmt"
/*
責任鏈模式
組成:由多個處理器及處理器處理標誌串聯組成
作用:常用於處理流水線事務,利用多個處理器對同一個對象進行處理,可以利用各處理器開關
場景:常見的獲取參數、fetch數據、邏輯處理數據、返回參數一系列數據連續化處理
優點:將複雜的流水線處理邏輯簡化為一個個單元,操作較為便捷,可以隨意在處理器之間串聯穿插新處理器
*/
// CalProcessor 處理器抽象介面
type CalProcessor interface {
SetNextProcessor(processor CalProcessor)
ProcessFor(calIdentity *CalIdentity)
}
// CalIdentity 處理對象實體
type CalIdentity struct {
A int
B int
sum int
hasGetA bool // GetAProcessor開關:是否獲取到A
hasGetB bool // GetBProcessor開關:是否獲取到B
hasAdd bool // SumProcessor開關:A與B是否相加
isComplete bool // CompleteProcessor開關:完成計算
}
// baseCalProcessor 基類實現CalProcessor
type baseCalProcessor struct {
nextCalProcessor CalProcessor
}
// SetNextProcessor 用於串聯處理器
func (b *baseCalProcessor) SetNextProcessor(processor CalProcessor) {
b.nextCalProcessor = processor
}
// ProcessFor 用於承接處理器的執行邏輯
func (b *baseCalProcessor) ProcessFor(calIdentity *CalIdentity) {
if b.nextCalProcessor != nil {
b.nextCalProcessor.ProcessFor(calIdentity)
}
}
// GetAProcessor 獲取數字A處理器
type GetAProcessor struct {
baseCalProcessor
}
func (g *GetAProcessor) ProcessFor(calIdentity *CalIdentity) {
if !calIdentity.hasGetA {
fmt.Println("getting number A.")
}
fmt.Println("A")
calIdentity.hasGetA = true
g.nextCalProcessor.ProcessFor(calIdentity)
}
// GetBProcessor 獲取數字B處理器
type GetBProcessor struct {
baseCalProcessor
}
func (g *GetBProcessor) ProcessFor(calIdentity *CalIdentity) {
if !calIdentity.hasGetA {
fmt.Println("didn't get number A.")
return
}
fmt.Println("B")
calIdentity.hasGetB = true
g.nextCalProcessor.ProcessFor(calIdentity)
}
// SumProcessor 加法處理器
type SumProcessor struct {
baseCalProcessor
}
func (g *SumProcessor) ProcessFor(calIdentity *CalIdentity) {
if !calIdentity.hasGetA || !calIdentity.hasGetB {
fmt.Println("didn't get number A or B")
return
}
fmt.Println("A plus B")
calIdentity.hasAdd = true
g.nextCalProcessor.ProcessFor(calIdentity)
}
// CompleteProcessor 完成處理器
type CompleteProcessor struct {
baseCalProcessor
}
func (c *CompleteProcessor) ProcessFor(calIdentity *CalIdentity) {
if !calIdentity.hasGetA || !calIdentity.hasGetB || !calIdentity.hasAdd {
fmt.Println("cal not done.")
return
}
fmt.Println("done")
calIdentity.isComplete = true
return
}
測試類
package burden_chain
import "testing"
func TestChainResponsibility(t *testing.T) {
calProcessor := BuildCalProcessorChain()
calIdentity := &CalIdentity{
A: 0,
B: 0,
sum: 0,
hasGetA: false,
hasGetB: true,
hasAdd: false,
isComplete: false,
}
calProcessor.ProcessFor(calIdentity)
}
// BuildCalProcessorChain: GetAProcessor -> GetBProcessor -> SumProcessor -> CompleteProcessor
func BuildCalProcessorChain() CalProcessor {
completeCheckNode := &CompleteProcessor{}
sumCheckNode := &SumProcessor{}
sumCheckNode.SetNextProcessor(completeCheckNode)
getBCheckNode := &GetBProcessor{}
getBCheckNode.SetNextProcessor(sumCheckNode)
getACheckNode := &GetAProcessor{}
getACheckNode.SetNextProcessor(getBCheckNode)
return getACheckNode
}
命令模式
組成:接受者、指令觸發器
作用:將請求方法參數化,將指令抽象,便於在指令與指令之間建立獨立的邏輯操作關係
場景:適用於任務定製需求,比如818活動等等,在特點的時間節點,使用特定的功能需求。
優點:將指令單元化,通過統一的的Execute介面方法進行調用,屏蔽各個請求的差異,便於多命令組裝、回滾,屏蔽各個請求的差異
接受者
package order_pattern
type ReceiverA struct {
height int
width int
}
func (s *ReceiverA) SetHeight(height int) {
s.height = height
}
func (s *ReceiverA) SetWidth(width int) {
s.width = width
}
func (s *ReceiverA) Shutdown() string {
return "shut down this formulation."
}
指令觸發器
package order_pattern
import "fmt"
/*
命令模式
組成:接受者、指令觸發器
作用:將請求方法參數化,將指令抽象,便於在指令與指令之間建立獨立的邏輯操作關係
優點:將指令單元化,通過統一的的Execute介面方法進行調用,屏蔽各個請求的差異,便於多命令組裝、回滾,屏蔽各個請求的差異
*/
type CalCommand interface {
Execute() string
}
// CalCircleCommand 計算周長
type CalCircleCommand struct {
receiver *ReceiverA
}
// 指令將接受者內嵌
func NewCalCircleCommand(receiver *ReceiverA) *CalCircleCommand {
return &CalCircleCommand{receiver: receiver}
}
// 利用各個指令內置方法,將不同指令的執行過程屏蔽,便於擴展
func (c *CalCircleCommand) Execute() string {
c.receiver.SetWidth(2)
c.receiver.SetHeight(3)
return fmt.Sprintf("the circle of receiver is %.2f", float64(2*(c.receiver.width+c.receiver.height)))
}
// CalAreaCommand 計算面積
type CalAreaCommand struct {
receiver *ReceiverA
}
func NewCalAreaCommand(receiver *ReceiverA) *CalAreaCommand {
return &CalAreaCommand{receiver: receiver}
}
func (c *CalAreaCommand) Execute() string {
c.receiver.SetWidth(2)
c.receiver.SetHeight(3)
return fmt.Sprintf("the area of receiver is %.2f", float64(c.receiver.height*c.receiver.width))
}
type CommandInvoker struct {
calCommand CalCommand
}
func (c *CommandInvoker) SetCommand(calCommand CalCommand) {
c.calCommand = calCommand
}
func (c *CommandInvoker) ExecuteCommand() string {
return c.calCommand.Execute()
}
測試類
package order_pattern
import (
"fmt"
"testing"
)
func TestOrderPattern(t *testing.T) {
receiver := new(ReceiverA)
commandInvoker := new(CommandInvoker)
circleCommand := NewCalCircleCommand(receiver)
commandInvoker.SetCommand(circleCommand)
fmt.Println(commandInvoker.ExecuteCommand())
areaCommand := NewCalAreaCommand(receiver)
commandInvoker.SetCommand(areaCommand)
fmt.Println(commandInvoker.ExecuteCommand())
}
迭代器模式
組成:創建迭代器的工廠方法介面Iterable、迭代器本身本身的介面memberIterator
作用:用於在不暴露集合底層表現形式的情況下遍歷集合中的所有元素,即在迭代器的幫助下,客戶端可以用一個迭代器介面以相似的方法遍歷不同集合中的元素
場景:適用於為迭代遍歷來自兩個及以上不同類型的集合中的元素,無視集合的底層類型,只通過暴露出的Next和HasNext來訪問元素
實體類
package iterator_pattern
import "fmt"
// Member 成員抽象介面
type Member interface {
Info() string
}
// Teacher 教師實體
type Teacher struct {
Name string
Subject string
}
// NewTeacher 創建教師實體
func NewTeacher(name, subject string) *Teacher {
return &Teacher{
Name: name,
Subject: subject,
}
}
// Info 返回教師信息
func (t *Teacher) Info() string {
return fmt.Sprintf("%s老師負責的科目-%s", t.Name, t.Subject)
}
// Student 學生實體
type Student struct {
Name string
SumScore int
}
// NewStudent 創建學生實體
func NewStudent(name string, score int) *Student {
return &Student{
Name: name,
SumScore: score,
}
}
// Info 返回學生信息
func (s *Student) Info() string {
return fmt.Sprintf("%s同學考試分數:%d", s.Name, s.SumScore)
}
迭代器
package iterator_pattern
/*
迭代器模式
組成:創建迭代器的工廠方法介面Iterable、迭代器本身本身的介面memberIterator
作用:用於在不暴露集合底層表現形式的情況下遍歷集合中的所有元素,即在迭代器的幫助下,客戶端可以用一個迭代器介面以相似的方法遍歷不同集合中的元素
場景:適用於為迭代遍歷來自兩個及以上不同類型的集合中的元素,無視集合的底層類型,只通過暴露出的Next和HasNext來訪問元素
*/
// Iterator 迭代器抽象介面
type Iterator interface {
Next() Member
HasNext() bool
}
// memberIterator 迭代器實現類
type memberIterator struct {
class *Class
index int
}
// Next 獲取迭代器中的下一個元素
func (m *memberIterator) Next() Member {
if m.index == -1 { // 若游標是-1,則返回老師
m.index++
return m.class.Teacher
}
student := m.class.Students[m.index] // 游標大於等於0,則返回學生
m.index++
return student
}
// HasNext 判斷是否存在下一個元素
func (m *memberIterator) HasNext() bool { // 判斷是否還有剩餘需要迭代的元素
return m.index < len(m.class.Students)
}
// Iterable 可迭代集合介面,實現此介面返回迭代器
type Iterable interface {
CreateIterator() Iterator
}
// Class 包括班級id、老師和同學
type Class struct {
Id int
Teacher *Teacher
Students []*Student
}
// NewClass 根據班級id、老師創建班級
func NewClass(id int, teacherName, subject string) *Class {
return &Class{
Id: id,
Teacher: NewTeacher(teacherName, subject),
}
}
// GetClassID 獲取班級id
func (c *Class) GetClassID() int {
return c.Id
}
// AddStudent 增加學生
func (c *Class) AddStudent(students ...*Student) {
c.Students = append(c.Students, students...)
}
// CreateIterator 創建班級迭代器
// 迭代器兩要素:班級實體、迭代索引
func (c *Class) CreateIterator() Iterator {
return &memberIterator{
class: c, // 待迭代容器
index: -1, // 迭代索引初始化為-1,從老師開始迭代
}
}
測試類
package iterator_pattern
import (
"fmt"
"testing"
)
func TestIterator(t *testing.T) {
class := NewClass(1, "cjh", "CS")
class.AddStudent(NewStudent("張三", 410),
NewStudent("李四", 400))
fmt.Printf("%d班級成員如下:\n", class.GetClassID())
classIterator := class.CreateIterator()
for classIterator.HasNext() {
member := classIterator.Next()
fmt.Println(member.Info())
}
}