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())
}
}
go-浅学设计模式随记的更多相关文章
- junit浅学笔记
JUnit是一个回归测试框架(regression testing framework).Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(Wh ...
- 从零开始单排学设计模式「装饰模式」黑铁 I
阅读本文大概需要 3.6 分钟. 本篇是设计模式系列的第四篇,虽然之前也写过相应的文章,但是因为种种原因后来断掉了,而且发现之前写的内容也很渣,不够系统. 所以现在打算重写,加上距离现在也有一段时间了 ...
- 从零开始单排学设计模式「策略模式」黑铁 II
阅读本文大概需要 1.7 分钟. 本篇是设计模式系列的第三篇,虽然之前也写过相应的文章,但是因为种种原因后来断掉了,而且发现之前写的内容也很渣,不够系统.所以现在打算重写,加上距离现在也有一段时间了, ...
- 从零开始单排学设计模式「简单工厂设计模式」黑铁 III
阅读本文大概需要 2 分钟. 本篇是设计模式系列的第二篇,虽然之前也写过相应的文章,但是因为种种原因后来断掉了,而且发现之前写的内容也很渣,不够系统.所以现在打算重写,加上距离现在也有一段时间了,也算 ...
- 从零开始单排学设计模式「UML类图」定级赛
阅读本文大概需要 3.5 分钟. 本篇是设计模式系列的开篇,虽然之前也写过相应的文章,但是因为种种原因后来断掉了,而且发现之前写的内容也很渣,不够系统. 所以现在打算重写,加上距离现在也有一段时间了, ...
- 浅学JavaScript
JavaScript是互联网上最流行的脚本语言,可广泛用于服务器.PC.笔记本电脑智能手机等设备: 对事件的反应: <!DOCTYPE html> <html> <hea ...
- 【一起学设计模式】观察者模式实战:真实项目中屡试不爽的瓜娃EventBus到底如何实现观察者模式的?
申明 本文章首发自本人公众号:壹枝花算不算浪漫,如若转载请标明来源! 感兴趣的小伙伴可关注个人公众号:壹枝花算不算浪漫 22.jpg 前言 之前出过一个设计模式的系列文章,这些文章和其他讲设计模式的文 ...
- opengl 入门浅学(一)
因为要做图形学的实验,又是要以OPENGL为基础,所以就稍微在网上查了一些资料. 我是带着目的去学习的,所以就没有打基础之类的学很深,浅尝. 今天试着搭简单框架,画出一个图形.大神请出门左转. #in ...
- 浅学html
数据库web端需要了解html等语言,就初浅学习一下 <!DOCTYPE html> <html> <head> <meta charset="ut ...
- 浅谈设计模式--装饰者模式(Decorator Pattern)
挖了设计模式这个坑,得继续填上.继续设计模式之路.这次讨论的模式,是 装饰者模式(Decorator Pattern) 装饰者模式,有时也叫包装者(Wrapper),主要用于静态或动态地为一个特定的对 ...
随机推荐
- Truenas core 13连接LDAP,获取AD域用户及自动分配权限---chatGPT回复,未做证实
要在TrueNAS Core 13上连接LDAP并从AD域中获取用户,请按照以下步骤操作: 在TrueNAS Core 13上登录到WebUI. 转到"网络"菜单并选择" ...
- web实践4
web实践4 20201303张奕博 2023.1.27 创建胡萝卜 接着,在地面上添加一些胡萝卜 .胡萝卜身体部分是通过四棱柱 CylinderBufferGeometry 实现的,然后通过 Box ...
- 解决多行文本超出显示省略号webpack打包后失效的问题
开发环境没问题: 但是在打包部署后就失效了: 经过对比后发现是因为: 缺少了 -webkit-box-orient: vertical; 导致 解决方案 : /* ! autoprefixer: o ...
- SpringBoot中常见问题
Invalid bound statement(not found): 异常原因:编译之后的mapper文件中的.xml文件未编译, 解决方法:在pom.xml文件中添加如下配置,添加位置为build ...
- 配置tomcat 服务 启动模式
1配置Tomcat的环境变量,其步骤如下: 计算机右击属性,打开环境变量---系统变量---新建变量名:CATALINA_HOME,变量值为:D:\Program Files\Apache Softw ...
- linux办公
办公环境.生产环境: centos.redhat.big cloud 1.改PS1:生产主机的主机名太长了,每次显示占半行 [root@10.0.0.11 ~]$ echo $PS1 [\u@10.0 ...
- memoのPython和3D那点事
首先来说,python想要搞点啥3D的玩意,是真麻烦.可以撤了. 少侠别走! 虽然很艰难,我还是找到一些体验不错的python库,可以拿来用. 首先,就是这里.前提是需要有conda.我直接装了个mi ...
- Java基础学习:6、方法的重载和可变参数
一.方法重载: 基本介绍: Java中允许在一个类中,多个同名方法的存在,到要求形参列表不一致. 注意事项: 1.方法名:必须一致. 2.形参列表:必须不同(形参类型或个数或顺序至少有一样不同,参数名 ...
- nginx status code 状态码
目录 1XX 临时响应并需要请求者继续执行操作的状态代码 2XX 成功功处理了请求的状态代码 3XX 重定向 要完成请求,需要进一步操作 通常用来重定向 4XX 表示请求可能出错,妨碍了服务器的处理 ...
- 是时候开始写总结了-今日总结-vue单页面制作
今天哥给了我一个页面,让做出类似的. <h2>就直接说下页面用到的知识点吧</h2> 首先说下该页面使用的是vue2+less 直接写 导入模块时就只导入了cnpm i l ...