分享好友 最新动态首页 最新动态分类 切换频道
23种设计模式-Golang(完整版)
2024-12-27 00:32

完整代码链接:https://github.com/ziyifast/easy_design_mode
🚀:欢迎star哦

1.1 简单工厂模式(simple factory:不同协议有生成不同downloader

①解析

go 语言没有构造函数,所以我们一般是通过 NewXXX 函数来初始化相关类。 NewXXX 函数返回接口时就是简单工厂模式,也就是说 Golang 的一般推荐做法就是简单工厂。

  • 在这个 simplefactory 包中只有API 接口和 NewAPI 函数为包外可见,封装了实现细节。
②代码
 

1.2 工厂方法模式(factory method:不同品牌手机有不同工厂

①解析

工厂方法模式使用子类的方式延迟生成对象到子类中实现。

Go 中不存在继承 所以使用匿名组合来实现

示例步骤

  1. 定义接口type operator interface
    • 参数a
    • 参数b
    • result:具体业务方法
  2. 定义type BaseFactory struct:提供方法,用于设置a、b参数
    • 参数a
    • 参数b
  3. 根据不同操作,定义不同工厂类(addFactory、minusFactory
    • addFactory实现operator的result:a+b
    • minusFactory实现operator的result:a-b
  4. addFactory、minusFactory分别提供Create方法

简单工厂:唯一工厂类,一个产品抽象类,工厂类的创建方法依据入参判断并创建具体产品对象。
工厂方法:多个工厂类,一个产品抽象类,利用多态创建不同的产品对象,避免了大量的if-else判断。
抽象工厂:多个工厂类,多个产品抽象类,产品子类分组,同一个工厂实现类创建同组中的不同产品,减少了工厂子类的数量。

②代码
 

1.3 创建者模式(builder:上架商品包含命名+设置价格+数量等

①解析

将build一个物品拆分为几个部分
示例步骤

  1. 定义接口type goodsBuilder interface
    • setName
    • setPrice
    • setCount
    • *Goods
  2. 定义具体实现结构体type ConcreteBuilder struct
    • 实现goodsBuilder接口
  3. 提供NewGoodsBuilder接口,返回ConcreteBuilder实现类
②代码
 

1.4 原型模式(prototype:clone对象,复制自身

①解析

原型模式使对象能复制自身,并且暴露到接口中,使客户端面向接口编程时,不知道接口实际对象的情况下生成新的对象。

原型模式配合原型管理器使用,使得客户端在不知道具体类的情况下,通过接口管理器得到新的实例,并且包含部分预设定配置。

示例步骤

  1. 定义接口type Prototype interface
    • 包含clone方法:Clone() Prototype
  2. 定义结构体type ConcretePrototype struct
    • 实现clone方法:Clone() Prototype
②代码
 

1.5 单例模式(singleton:一个类只有一个实例

①解析

使用懒惰模式的单例模式,使用once.Do加锁保证线程安全
保证只有单个实例

单例模式

  1. 懒汉式:用到时才实例化(GetInstance,通过once.Do保证只加载一次
  2. 饿汉式:一开始就实例化(init
②代码
 
 

2.1 外观模式(facade:audioFixer+videoFixer

①解析

外观模式也叫门面模式,是一种结构型设计模式,它提供了一个统一的接口来访问子系统中的一组接口。这种模式通过定义一个高层接口来隐藏子系统的复杂性,使子系统更容易使用。
在Go语言中,我们可以使用结构体和接口来实现外观模式。

示例

  1. 定义audioFixer,实现fixer
  2. 定义videoFixer,实现fixer
  3. 定义AudioAndVideoFixer,组合audioFixer和videoFixer
②代码
 

2.2 适配器模式(adapter:阿里支付、维信支付等

①解析

适配器适合用于解决新旧系统(或新旧接口)之间的兼容问题,而不建议在一开始就直接使用

  • 适配器模式将一个类的接口,转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间

关键代码:
适配器中持有旧接口对象,并实现新接口

示例

  1. 定义阿里支付接口 type AliPayInterface interface,包含Pay方法
  2. 定义微信支付接口 type WeChatPayInterface interface,包含Pay方法
  3. 分别定义阿里支付和微信支付的实现类 AliPay 和 WeChatPay struct
  4. 定义目标接口 type TargetPayInterface interface,包含DealPay方法
  5. 定义TargetPayInterface接口实现类 PayAdapter struct,实现DealPay方法
    • 内部持有AliPayInterface和WeChatPayInterface对象,根据类型分别调用其Pay方法
②代码
 

2.3 代理模式(proxy:支付前的签名校验等

①解析

代理模式用于延迟处理操作或者在进行实际操作前后进行其它处理。

示例

  1. 定义PaymentService interface接口,包含pay方法
  2. 定义Alipay struct,实现PaymentService interface接口
  3. 定义paymentProxy struct,包含realPay(实现了PaymentService interface的结构体
  4. paymentProxy实现pay方法,调用realPay的pay方法之前和之后分别来添加一些额外的操作
②代码
 

2.4 享元模式(flyweight:优先从内存map中获取对象

①解析

享元模式从对象中剥离出不发生改变且多个实例需要的重复数据,独立出一个享元,使多个对象共享,从而节省内存以及减少对象数量。

示例

  1. 定义结构体ImageFlyweight struct,用于展示图像信息
  2. 定义ImageFlyweightFactory struct工厂,包含:maps map[string]*ImageFlyweight
  3. 提供方法:GetImageFlyweight(name string) *ImageFlyweight
    • 先从map中获取,如果map中存在,则直接返回;如果不存在则New一个ImageFlyweight,存入map中,然后返回
  4. 提供方法GetImageFlyweightFactory,用于获取工厂
②代码
 

2.5 装饰模式(decorator:换个皮肤,增加car的价钱

①解析

装饰模式使用对象组合的方式动态改变或增加对象行为。

Go语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式。

使用匿名组合,在装饰器中不必显式定义转调原对象方法。

示例

  1. 定义PriceDecorator interface接口
    • 包含DecoratePrice(c Car) Car方法,用于增加车的price
  2. 定义ExtraPriceDecorator结构体,实现PriceDecorator接口
    • 包含ExtraPrice字段,用于给传入的car增加额外的price,最后返回car
②代码
 

2.6 桥模式(bridge:不同电脑可桥接不同打印机

①解析

桥接模式分离抽象部分和实现部分。使得两部分独立扩展。

桥接模式类似于策略模式,区别在于策略模式封装一系列算法使得算法可以互相替换。

策略模式使抽象部分和实现部分分离,可以独立变化。

如果你想要拆分或重组一个具有多重功能的庞杂类(例如能与多个数据库服务器进行交互的类,可以使用桥接模式。
如果你希望在几个独立维度上扩展一个类,可使用该模式。
如果你需要在运行时切换不同实现方法,可使用桥接模式。

示例

  1. 定义Printer interface接口,包含print方法。
  2. 定义Computer interface接口,包括SetPrinter(Printer)以及print方法。
  3. 创建不同Printer、Computer通过SetPrinter方法,来实现电脑和打印机的排列组合
②代码
 

2.7 组合模式(composite:目录包含多个文件

①解析

组合模式统一对象和对象集,使得使用相同接口使用对象和对象集。

组合模式常用于树状结构,用于统一叶子节点和树节点的访问,并且可以用于应用某一操作到所有子节点。

示例:以飞书文档接口为例,一个目录下面可以包含多个子文件

我们最先想到的做法就是:将文件和目录放在一个类中,新增一个字段,用于判断是文件还是目录。但这样并不优雅。因为文件和目录是不同的,各自有各自的特性,将特有的内容放到一个类里,不满足单一职责原则。
下面将展示通过组合模式来实现文档管理结构

  1. 定义FileSystem interface,抽取文档和目录的公共部分
    • Display(separator string)
  2. 定义FileCommon struct,抽取文件和目录的公共部分
    • fileName string
    • SetFileName(fileName string)
  3. 定义FileNode struct,用于表示文件类。并实现Display方法
    • FileCommon
  4. 定义DirectoryNode struct,用于表示目录类。并实现Display方法。因为目录下可以存放多个文件,因此需要提供addFile方法
    • FileCommon
    • nodes []FileSystemNode
    • Add(f FileSystemNode)
②代码
 
 

3.1 中介者模式(mediator:租房中介

①解析

中介者模式封装对象之间互交,使依赖变的简单,并且使复杂互交简单化,封装在中介者中。

例子中的中介者使用单例模式生成中介者。

中介者的change使用switch判断类型。

使用场景

  1. 当一些对象和其他对象紧密耦合以致难以对其进行修改时,可使用中介者模式。
  2. 当组件因过于依赖其他组件而无法在不同应用中复用时,可使用中介者模式。
  3. 如果为了能在不同情景下复用一些基本行为,导致你需要被迫创建大量组件子类时,可使用中介者模式。

示例

  1. 定义MessageMediator interface中介者接口,包含sendMessage(msg string, user User)、receiveMessage() string方法
  2. 定义具体中介者实现类,ChatRoom struct,属性包含Message string
    • 实现sendMessage方法,将消息发送给用户
  3. 定义type User struct
    • name string
    • mediator Mediator
  4. 用户通过mediator发送消息,通过mediator(chatroom)接受消息
②代码
 

3.2 观察者模式(observer:发布订阅

①解析

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

一个对象的改变会触发其它观察者的相关动作,而此对象无需关心连动对象的具体实现。
关键:被观察者持有了集合存放观察者 (收通知的为观察者);类比消息队列的发布订阅,你订阅了此类消息,当有消息来时,我就通知你

示例

  1. 定义Customer interface,包含update() 方法
  2. 定义CustomerA、CustomerB结构体,实现update()方法
  3. 定义newsOffice struct,包含customers字段,用于存储观察者,后续有事件发生时通知观察者
    • customers []Customer
    • func addCustomer(customer Customer)
    • func removeCustomer(customer Customer)
    • func newsComing() 新报纸到来,调用notifyAll方法通知所有观察者
    • func notifyAll()
②代码
 

3.3 命令模式(command:命令服务员倒水、命令厨师炒菜

①解析

命令模式本质是把某个对象的方法调用封装到对象中,方便传递、存储、调用。

示例中把主板单中的启动(start)方法和重启(reboot)方法封装为命令对象,再传递到主机(box)对象中。于两个按钮进行绑定

第一个机箱(box1)设置按钮1(button1) 为开机按钮2(button2)为重启。
第二个机箱(box1)设置按钮2(button2) 为开机按钮1(button1)为重启。
从而得到配置灵活性。

除了配置灵活外,使用命令模式还可以用作

批处理
任务队列
undo, redo
等把具体命令封装到对象中使用的场合

示例

  1. 定义ICommand interface接口,包含execute()方法
  2. 定义Invoker struct,包含commands []ICommand
    • 包含Call():用于执行commands中的所有方法
  3. 定义TV struct,包含shutdown和turnOn方法
  4. 定义ShutdownCommand struct,包含tv,实现execute()方法
    • t.tv.Shutdown()
  5. 定义TurnOnCommand struct,包含tv,实现execute()方法
    • t.tv.turnOn()
②代码
 

3.4 迭代器模式(iterator:集合遍历

①解析

迭代器模式用于使用相同方式送代不同类型集合或者隐藏集合类型的具体实现。

可以使用迭代器模式使遍历同时应用送代策略,如请求新对象、过滤、处理对象等。

示例

  1. 定义Iterator interface
    • Next() interface{}
    • HasNext() bool
  2. 定义NumberIterator struct结构体,实现Iterator接口
  3. 定义Numbers struct
    • numbers []int
    • func Iterator(),用于获取number的迭代器
②代码
 

3.5 模板方法模式(template method:炒菜之前都需要打开煤气+开火+加油等

①解析

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

  • 通用步骤在抽象类中实现,变化的步骤在具体的子类中实现
  • 做饭,打开煤气,开火(做饭, 关火,关闭煤气。除了做饭其他步骤都是相同的,抽到抽象类中实现

示例

  1. 定义type Cooker interface{},包含做饭的全部步骤,open()、openfire()、cook()、close()、closefire()等
  2. 定义type CookMenu struct抽象类,实现做饭的通用步骤,如:打开煤气、打开开关、关闭煤气、关闭开关。具体的做饭内容cook()在子类中实现
  3. 定义type ChaojiDan struct,继承CookMenu(属性里包含CookMenu,实现具体做饭的步骤:炒鸡蛋
    • CookMenu
    • func (ChaoJiDan) cook() {
      fmt.Println(“做炒鸡蛋”)
      }
②代码
 

3.6 策略模式(strategy:支付可采用现金支付、信用卡支付(策略)

①解析

定义一系列算法,让这些算法在运行时可以互换,使得分离算法,符合开闭原则。

示例

  1. 定义PaymentStrategy interface 接口
    • Pay(amount float64) error
  2. 定义实现类,CreditCardPaymentStrategy、CashPaymentStrategy
    • 分别实现Pay(amount float64) error方法
  3. 定义上下文对象类PaymentContext
    • amount float64
    • strategy PaymentStrategy
  4. PaymentContext提供Pay()方法,调用strategy.Pay(amount)方法
    • p.strategy.Pay(p.amount)
  5. 提供NewPaymentContext方法,返回*PaymentContext对象
  6. 根据不同策略,调用NewPaymentContext方法,返回不同PaymentContext对象,实现不同的支付
②代码
 

3.7 状态模式(state:QQ包括离线、在线、忙碌等状态

①解析

状态模式用于分离状态和行为。

示例

  1. 定义ActionState interface接口,包含:状态所关联的 查看、评论、发布行为
    • View()
    • Comment()
    • Post()
  2. 定义ActionState的实现类
    • NormalState:账号正常状态
    • RestrictState:账号受限制状态
    • CloseState:账号被封状态
  3. 定义type Account struct
    • state *ActionState
    • healthValue:健康值对应不同的状态
    • 分别实现View、Comment、Post方法,调用state的方法:a.state.View()
    • 实现changeState方法,根据healthValue设置state
  4. 定义NewAccount(healthValue int) *Account:创建一个账号并设置健康值
 

3.8 备忘录模式(memento:文本的撤销与重做

①解析

备忘录模式用于保存程序内部状态到外部,又不希望暴露内部状态的情形。

允许在不破坏封装性的前提下保存和恢复对象的内部状态,程序内部状态使用窄接口传递给外部进行存储,从而不暴露程序实现细节。

备忘录模式同时可以离线保存内部状态,如保存到数据库,文件等。

该模式涉及三个主要角色

  • Originator(发起人:Originator 是拥有内部状态的对象
  • Memento(备忘录:Memento 是 Originator 的快照
  • Caretaker(负责人:Caretaker 负责备份和恢复 Memento。

示例

state暂时用string来代替,实际可用struct
案例演示:实现一个文本编辑器,提供撤销和重做功能

  1. 定义Originator interface, Originator 发起人:用于保存或者恢复当前状态(备忘录
    • Save() Memento
    • Restore(m Memento)
  2. 定义Memento interface ,提供方法用于获取当前状态【备忘录:记录当前状态】
    • GetState() string
  3. 定义TextMemento struct,实现Memento接口,保存state
  4. 定义textEditor struct,实现Originator接口
    • state string
    • func Save() Memento
    • func Restore(m Memento)
    • func SetState(state string)
  5. 定义Caretaker struct
    • mementos []Memento
    • currentIndex int
    • func AddMemento(m Memento)
    • func Undo(t *TextEditor)
    • func Redo(t *TextEditor)
②代码
 

3.9 解释器模式(interpreter:SQL语法解析器

①解析

解释器模式(Interpreter Pattern)是一种行为设计模式,它定义了一种语言,用于解释一些特定的领域问题。
在该模式中,将语言中的元素映射到类中,并定义它们之间的关系。然后,可以使用这些类来解释表达式,以解决特定的问题。

应用场景

  1. 处理配置文件:json、yaml
  2. 模板引擎:模板引擎处理模板和一组变量以产生输出。模板是DSL的一个例子,可以使用Interpreter来解析和处理模板。
  3. 数学表达式计算器

解释器模式中的关键组件

表达式接口:表示抽象语法树的元素并定义解释表达式的方法。
具体表达式:实现表达式接口的结构,表示语言语法的各种规则或元素。
上下文对象:用于保存解释过程中所需的任何必要信息或状态。
Parser 或 Builder:负责根据输入表达式构建抽象语法树的组件。

示例

构建一个计算器

  1. 定义Expression interface接口,包含Interpret() int方法
  2. 定义NumberExpression struct,实现Interpret() int方法
    • val int
  3. 定义AdditionExpression struct,实现Interpret() int方法,返回两数之和
    • left Expression
    • right Expression
    • func Interpret() int {
      }
  4. 定义SubtractionExpression struct,实现Interpret() int方法,返回两数之差
    • left Expression
    • right Expression
    • func Interpret() int {
      }
  5. 定义Parser struct,存储输入表达式exp、index解析索引位置、prev 上一个表达式
    • exp []string
    • index int
    • prev Expression
    • func Parse() Expression {
      }
    • func newAdditionExpression() Expression{
      }
    • func newSubtractionExpression() Expression{
      }
②代码
 

3.10 职责链模式(chain of responsibility:层层上报处理刑事案件

①解析

职责链模式是一种行为设计模式,定义了一系列对象,每个对象可以选择处理某个请求,也可以将该请求传给链中的下一个对象。

模式结构(职责链模式包含以下角色

  • 抽象处理器(Handler:定义出一个处理请求的接口。
  • 具体处理器(ConcreteHandler:实现抽象处理器的接口,处理它所负责的请求。如果不处理该请求,则把请求转发给它的后继者。
  • 客户端(Client:创建处理器对象,并将请求发送到某个处理器。

示例

演示国家刑事案件处理流程,下级先处理,如果处理不了,交给下一个

  1. 定义Handler interface接口
    • SetNext(handler Handler) //设置下一个处理器
    • Handle(request int) //处理请求
  2. 定义type TownHandler struct
    • NextHandler Handler //它的下一个处理器
    • Handle(request int) :如果案件级别高于20,就交给下一handler处理
    • func SetNext(handler Handler)
  3. 定义type CityHandler struct
    • NextHandler Handler //它的下一个处理器
    • Handle(request int) :如果案件级别高于100,就交给下一handler处理
    • func SetNext(handler Handler)
  4. 定义type ProvinceHandler struct
    • NextHandler Handler //它的下一个处理器
    • Handle(request int)
    • func SetNext(handler Handler)
②代码
 

3.11 访问者模式(visitor:dev、pro打印不同信息

①解析

访问者模式是一种操作一组对象的操作,它的目的是不改变对象的定义,但可以新增不同的访问者来定义新的操作。
访问者的核心思想是为了访问比较复杂的数据结构,不去改变原数据结构,而是把对数据的操作抽象出来,在访问的过程中以回调形式在访问者中处理逻辑操作。
如果要新增一组操作,那么只需要增加一个新的访问者。

示例

根据不同环境打印不同内容,在生产环境和开发环境中打印处不同的内容

  1. 定义IVisitor interface
    • Visit()
  2. 定义ProductionVisitor struct,实现IVisitor接口
    • env string
    • func Visit():判断env如果是生产环境,则打印生产环境的内容
  3. 定义DevelopmentVisitor struct,实现IVisitor接口
    • env string
    • func Visit():判断env如果是开发环境,则打印开发环境的内容
  4. 定义IElement interface接口
    • func Accept(IVisitor)
  5. 定义Element struct,实现IElement接口
    • visitors []IVisitor
  6. 定义ExampleLog struct(要打印的日志
    • Element
    • 实现print方法,遍历visitors,调用每个visitor的Visit方法
②代码
最新文章
贵宾犬能吃香蕉吗 饮食禁忌有哪些
贵宾犬是能吃香蕉的,但如果是没有打疫苗的幼犬,建议不要给它喂食香蕉,否则容易引起狗狗腹泻。此外,也不可给狗狗食用太多,过多会导致肠道菌群失衡。贵宾犬是可以吃香蕉的,在狗狗便秘或食欲不好的时候给于适当的香蕉可以起到调节作用,
高清美女写真生成:以AI为助手,轻松实现你的梦幻场景!
DALL-E 2DALL-E 2是OpenAI推出的一款先进工具,凭借其强大的生成能力,用户只需简单输入文本描述,工具便可以生成高质量、符合描述的图像。DALL-E 2不仅能制作超逼真的美女照片,还能够根据用户需求加入背景、道具和风格等。虽然它拥有惊人
设计师必用的五个AI绘图神器?第一个太重磅!
前言       以往绘制设计图时,需要从零开始构思、草拟、搜集素材、精细调整每个元素,这一连串步骤既耗时又费力,往往需要数小时乃至数日的不懈努力。      而今,借助AI绘图工具,这一切变得截然不
退本《DeePLAPP》遭遇任务骗局,提现无门怎么办?
DeePLAPP遭遇任务骗局,提现无门怎么办?技术出嘿『溦:9836356』(一)希望阅读此文的读者能够及时采取措施以减少损失;请及时与团队联系提供解决方案(文章下面图片有咨询方式)若想追回损失资产,务必仔细阅读以下内容。【JFHHERYERY】2024年
用AI绘画工具一键生成超逼真美女写真,快来试试!
步骤二:选择模式在主界面中选择“美女写真生成”模式,准备开始你的创作之旅。步骤三:输入描述在输入框中输入您想要的主题与细节,比如“优雅的中国风美女”。步骤四:生成图像点击“生成”按钮,等待几秒钟,系统将自动为您生成相应的美
靠产品力说话,坦克300发动机表现如何
在汽车市场日益激烈的竞争中,消费者对汽车的需求逐渐转向越野性能的提升,尤其是年轻一代,他们追求个性化和与众不同的座驾。在这样的背景下,国产汽车品牌纷纷推出满足市场需求的硬派越野SUV,其中坦克300凭借其卓越的产品力脱颖而出。今
谷歌SEO时,该信赖哪个Keyword research工具?
在SEO的浩瀚宇宙中,关键词研究如同指南针,引领我们穿越信息迷雾,直击目标受众的心智。作为一名实战派SEOer,我深知选择合适的Keyword Research工具对于谷歌SEO的重要性。今天,就让我们一同探讨,哪些工具能成为我们信赖的伙伴,助力网
科大新闻 | 智能时代新文科本科教学论坛成功举办
12月8日,由中国科学技术大学人文与社会科学学院主办的智能时代新文科本科教学论坛在东校区人文楼顺利举行。专家学者共同探讨本科教学中的创新应用、课程设计优化、人才培养模式变革等核心议题,助力智能时代新文科本科教学的高质量发展。
移动硬盘删除的文件夹怎么恢复?这几招,真应该提早知道的
移动硬盘删除的文件夹怎么恢复?移动硬盘作为便携式存储设备,广泛应用于我们的工作、学习和生活中。但是,在使用过程中,不小心删除了重要文件夹的情况也时有发生。为了找回丢失误删的文件夹,接下来,我们会为你介绍一些实用的恢复方法,
盖世小鸡GameHub:手机变身PC游戏神器!
在数字娱乐飞速发展的今天,游戏行业逐渐突破了传统的设备限制,玩家的选择也愈加多样化。最近,国内知名模拟器品牌盖世小鸡宣布推出一款名为GameHub的PC模拟器应用,标志着手机游戏体验的一个重大突破。据悉,该应用预计将在2024年春节前
相关文章
推荐文章
发表评论
0评