go-浅学设计模式随记

责任链模式

组成:由多个处理器及处理器处理标志串联组成

作用:常用于处理流水线事务,利用多个处理器对同一个对象进行处理,可以利用各处理器开关

场景:常见逻辑层处理逻辑:获取参数、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())
   }
}

posted on 2022-12-30 15:40  小陈努力努力再努力  阅读(46)  评论(0编辑  收藏  举报