工厂模式 | Go设计模式实战
http://tigerb.cn/ 我的代码没有else系列-简单工厂 结合实际业务谈设计模式 业务场景 12调用一个服务生成静态页面不同的页面拥有不同的模块 不同的页面的数据结构不一样生成不同的页面对象 正常代码 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667package mainimport "fmt"const ( // CartConst 购物车列表页面 CartConst = "cart/list" // ProductConst 商品列表页面 ProductConst = "product/list")// Context 请求上下文type Context struct { URI string}// PageInterface PageInterfacetype PageIn...
并发组件 | Go设计模式实战
并发组件 | Go设计模式实战 嗯,Go设计模式实战系列,一个设计模式业务真实使用的golang系列。 http://tigerb.cn/ 前言本系列主要分享,如何在我们的真实业务场景中使用设计模式。 本系列文章主要采用如下结构: 什么是「XX设计模式」? 什么真实业务场景可以使用「XX设计模式」? 怎么用「XX设计模式」? 本文主要介绍「组合模式」结合Go语言天生的并发特性,如何在真实业务场景中使用。 之前文章《代码组件 | Go设计模式实战》已经介绍了「组合模式」的概念,以及在业务中的使用。今天我们结合Go语言天生的并发特性,升级「组合模式」为「并发组合模式」。 我们先来简单回顾下「组合模式」的知识,详细可以查看上篇文章《代码组件 | Go设计模式实战》 什么是「并发组合模式」?组合模式的概念: 一个具有层级关系的对象由一系列拥有父子关系的对象通过树形结构组成。 并发组合模式的概念: 一个具有层级关系的对象由一系列拥有父子关系的对象通过树形结构组成,子对象即可被串行执行,也可被并发执行 并发组合模式的优势: 原本串行的业务(存在阻塞的部分,比如网络IO等)可...
状态变换 | Go设计模式实战
状态变换 | Go设计模式实战 嗯,Go设计模式实战系列,一个设计模式业务真实使用的golang系列。 http://tigerb.cn/ 前言本系列主要分享,如何在我们的真实业务场景中使用设计模式。 本系列文章主要采用如下结构: 什么是「XX设计模式」? 什么真实业务场景可以使用「XX设计模式」? 怎么用「XX设计模式」? 本文主要介绍「状态模式」如何在真实业务场景中使用。 「状态模式」比较简单,就是算法的选取取决于于自己的内部状态。相较于「策略模式」算法的选取由用户决策变成内部状态决策,「策略模式」是用户(客户端)选择具体的算法,「状态模式」只是通过内部不同的状态选择具体的算法。 什么是「状态模式」? 不同的算法按照统一的标准封装,根据不同的内部状态,决策使用何种算法 「状态模式」和「策略模式」的区别 策略模式:依靠客户决策 状态模式:依靠内部状态决策 什么真实业务场景可以用「状态模式」? 具体算法的选取是由内部状态决定的 首先,内部存在多种状态 其次,不同的状态的业务逻辑各不相同 我们有哪些真实业务场景可以用「状态模式」呢? 比如,发送短信接口、限流等...
客户决策 | Go设计模式实战
客户决策 | Go设计模式实战 嗯,Go设计模式实战系列,一个设计模式业务真实使用的golang系列。 http://tigerb.cn/ 前言本系列主要分享,如何在我们的真实业务场景中使用设计模式。 本系列文章主要采用如下结构: 什么是「XX设计模式」? 什么真实业务场景可以使用「XX设计模式」? 怎么用「XX设计模式」? 本文主要介绍「策略模式」如何在真实业务场景中使用。 什么是「策略模式」?「策略模式」比较简单,大家平常工作中应该经常使用到,所以本文作为复习,帮助大家温故知新。我们先来看下定义: 不同的算法按照统一的标准封装,客户端根据不同的场景,决策使用何种算法。 上面的概念的关键词: 算法:就是行为 标准:就是interface 客户端:客户端是相对的,谁调用谁就是客户端 场景:判断条件 决策:判断的过程 概念很容易理解,不多说。 「策略模式」的优势: 典型的高内聚:算法和算法之间完全独立、互不干扰 典型的松耦合:客户端依赖的是接口的抽象方法 沉淀:每一个封装好的算法都是这个技术团队的财富,且未来可以被轻易的修改、复用 什么真实业务场景可以用「策略模...
订阅通知 | Go设计模式实战
订阅通知 | Go设计模式实战 嗯,Go设计模式实战系列,一个设计模式业务真实使用的golang系列。 http://tigerb.cn/ 前言本系列主要分享,如何在我们的真实业务场景中使用设计模式。 本系列文章主要采用如下结构: 什么是「XX设计模式」? 什么真实业务场景可以使用「XX设计模式」? 怎么用「XX设计模式」? 虽然本文的题目叫做“订阅通知”,但是呢,本文却主要介绍「观察者模式」如何在真实业务场景中使用。是不是有些不理解?解释下: 原因一,「观察者模式」其实看起来像“订阅通知” 原因二,“订阅通知”更容易被理解 什么是「观察者模式」? 观察者观察被观察者,被观察者通知观察者 我们用“订阅通知”翻译下「观察者模式」的概念,结果: “订阅者订阅主题,主题通知订阅者” 是不是容易理解多了,我们再来拆解下这句话,得到: 两个对象 被观察者 -> 主题 观察者 -> 订阅者 两个动作 订阅 -> 订阅者订阅主题 通知 -> 主题发生变动通知订阅者 观察者模式的优势: 高内聚 -> 不同业务代码变动互不影响 可复用 ...
代码组件 | Go设计模式实战
代码组件 | Go设计模式实战 嗯,Go设计模式实战系列,一个设计模式业务真实使用的golang系列。 http://tigerb.cn/ 前言本系列主要分享,如何在我们的真实业务场景中使用设计模式。 本系列文章主要采用如下结构: 什么是「XX设计模式」? 什么真实业务场景可以使用「XX设计模式」? 怎么用「XX设计模式」? 本文主要介绍「组合模式」如何在真实业务场景中使用。 什么是「组合模式」? 一个具有层级关系的对象由一系列拥有父子关系的对象通过树形结构组成。 组合模式的优势: 所见即所码:你所看见的代码结构就是业务真实的层级关系,比如Ui界面你真实看到的那样。 高度封装:单一职责。 可复用:不同业务场景,相同的组件可被重复使用。 什么真实业务场景可以用「组合模式」?满足如下要求的所有场景: Get请求获取页面数据的所有接口 前端大行组件化的当今,我们在写后端接口代码的时候还是按照业务思路一头写到尾吗?我们是否可以思索,「后端接口业务代码如何可以简单快速组件化?」,答案是肯定的,这就是「组合模式」的作用。 我们利用「组合模式」的定义和前端模块的划分去构建后端...
链式调用 | Go设计模式实战
链式调用 | Go设计模式实战 嗯,Go设计模式实战系列,一个设计模式业务真实使用的golang系列。 http://tigerb.cn/ 前言本系列主要分享,如何在我们的真实业务场景中使用设计模式。 本系列文章主要采用如下结构: 什么是「XX设计模式」? 什么真实业务场景可以使用「XX设计模式」? 怎么用「XX设计模式」? 本文主要介绍「责任链模式」如何在真实业务场景中使用。 什么是「责任链模式」? 首先把一系列业务按职责划分成不同的对象,接着把这一系列对象构成一个链,然后在这一系列对象中传递请求对象,直到被处理为止。 我们从概念中可以看出责任链模式有如下明显的优势: 按职责划分:解耦 对象链:逻辑清晰 但是有一点直到被处理为止,代表最终只会被一个实际的业务对象执行了实际的业务逻辑,明显适用的场景并不多。但是除此之外,上面的那两点优势还是让人很心动,所以,为了适用于目前所接触的绝大多数业务场景,把概念进行了简单的调整,如下: 首先把一系列业务按职责划分成不同的对象,接着把这一系列对象构成一个链,直到“链路结束”为止。(结束:异常结束,或链路执行完毕结束) 简单...
代码模板 | Go设计模式实战
代码模板 | Go设计模式实战 嗯,Go设计模式实战系列,一个设计模式业务真实使用的golang系列。 http://tigerb.cn/ 前言本系列主要分享,如何在我们的真实业务场景中使用设计模式。 本系列文章主要采用如下结构: 什么是「XX设计模式」? 什么真实业务场景可以使用「XX设计模式」? 怎么用「XX设计模式」? 本文主要介绍「模板模式」如何在真实业务场景中使用。 什么是「模板模式」?抽象类里定义好算法的执行步骤和具体算法,以及可能发生变化的算法定义为抽象方法。不同的子类继承该抽象类,并实现父类的抽象方法。 模板模式的优势: 不变的算法被继承复用:不变的部分高度封装、复用。 变化的算法子类继承并具体实现:变化的部分子类只需要具体实现抽象的部分即可,方便扩展,且可无限扩展。 什么真实业务场景可以用「模板模式」?满足如下要求的所有场景: 算法执行的步骤是稳定不变的,但是具体的某些算法可能存在变化的场景。 怎么理解,举个例子:比如说你煮个面,必然需要先烧水,水烧开之后再放面进去,以上的流程我们称之为煮面过程。可知:这个煮面过程的步骤是稳定不变的,但是在不同的...
访问者和双分派
https://refactoringguru.cn/design-patterns/visitor-double-dispatch 访问者和双分派让我们看看下面几何图形类的层次结构 (注意伪代码): 123456789101112131415161718192021222324252627interface Graphic is method draw()class Shape implements Graphic is field id method draw() // ...class Dot extends Shape is field x, y method draw() // ...class Circle extends Dot is field radius method draw() // ...class Rectangle extends Shape is field width, height method draw() // ...class CompoundGraphi...
工厂模式比较
https://refactoringguru.cn/design-patterns/factory-comparison 工厂模式比较本文将对下列概念之间的差异进行说明: 工厂 构建方法 静态构建 (或工厂) 方法 简单工厂 工厂方法 抽象工厂 你可以在网上找到这些术语的参考信息。 尽管它们看上去相似, 但其含义都不一样。 许多人没有意识到这一点, 从而出现了混淆和误解。 因此让我们搞清楚其中的不同之处, 一劳永逸地解决这个问题。 1. 工厂工厂是一个含义模糊的术语, 表示可以创建一些东西的函数、 方法或类。 最常见的情况下, 工厂创建的是对象。 但是它们也可以创建文件和数据库记录等其他东西。 例如, 下面这些东西都可以非正式地被称为 “工厂”: 创建程序 GUI 的函数或方法; 创建用户的类; 以特定方式调用类构造函数的静态方法。 一种创建型设计模式。 当某人说到 “工厂” 这个词时, 其具体含义通常可以根据上下文来确定。 但如果你有疑问, 可以直接提问。 毕竟作者本人有时候也没有搞清楚。 2. 构建方法构建方法在 《重构与模式》 中被定义为 “创建对象的方法”...
行为模式-解释器模式
行为模式-解释器模式亦称: interpreter 介绍解释器模式:定义一种方法和对应的解释器,使用解释器解释此方法的语句来执行; 解释器模式需要上下文类来定义和存储上下文,解释器类用来将语句来翻译成可执行程序; 解释器扩展和改变文化非常简单,构建完成后可以很方便地数据格式; 解释器模式会将非终结表达式递归解释,直到解释为终结符表达式; 场景 解释器模式适用于数据结构不规则,但数据要素相同的情况; 语法不能太复杂,复杂的最好使用解释形语言来实现以降低复杂性; golangjava12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061package mainimport "strings"//意图:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。//主要解决:对于一些固定文法构建一个解释句子的解释器。//何时使用:如果一种特定类型的问题发生的...
行为模式-访问者模式
https://refactoringguru.cn/design-patterns/visitor 行为模式-访问者模式亦称: Visitor 意图访问者模式是一种行为设计模式, 它能将算法与其所作用的对象隔离开来。 问题假如你的团队开发了一款能够使用巨型图像中地理信息的应用程序。 图像中的每个节点既能代表复杂实体 (例如一座城市), 也能代表更精细的对象 (例如工业区和旅游景点等)。 如果节点代表的真实对象之间存在公路, 那么这些节点就会相互连接。 在程序内部, 每个节点的类型都由其所属的类来表示, 每个特定的节点则是一个对象。 一段时间后, 你接到了实现将图像导出到 XML 文件中的任务。 这些工作最初看上去非常简单。 你计划为每个节点类添加导出函数, 然后递归执行图像中每个节点的导出函数。 解决方案简单且优雅: 使用多态机制可以让导出方法的调用代码不会和具体的节点类相耦合。 但你不太走运, 系统架构师拒绝批准对已有节点类进行修改。 他认为这些代码已经是产品了, 不想冒险对其进行修改, 因为修改可能会引入潜在的缺陷。 此外, 他还质疑在节点类中包含导出 XML ...
行为模式-模板方法模式
https://refactoringguru.cn/design-patterns/template-method 行为模式-模板方法模式亦称: Template Method 意图模板方法模式是一种行为设计模式, 它在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 问题假如你正在开发一款分析公司文档的数据挖掘程序。 用户需要向程序输入各种格式 (PDF、 DOC 或 CSV) 的文档, 程序则会试图从这些文件中抽取有意义的数据, 并以统一的格式将其返回给用户。 该程序的首个版本仅支持 DOC 文件。 在接下来的一个版本中, 程序能够支持 CSV 文件。 一个月后, 你 “教会” 了程序从 PDF 文件中抽取数据。 一段时间后, 你发现这三个类中包含许多相似代码。 尽管这些类处理不同数据格式的代码完全不同, 但数据处理和分析的代码却几乎完全一样。 如果能在保持算法结构完整的情况下去除重复代码, 这难道不是一件很棒的事情吗? 还有另一个与使用这些类的客户端代码相关的问题: 客户端代码中包含许多条件语句, 以根据不同的处理对象类型选择合适的...
行为模式-策略模式
https://refactoringguru.cn/design-patterns/strategy 行为模式-策略模式亦称: Strategy 意图策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。 问题一天, 你打算为游客们创建一款导游程序。 该程序的核心功能是提供美观的地图, 以帮助用户在任何城市中快速定位。 用户期待的程序新功能是自动路线规划: 他们希望输入地址后就能在地图上看到前往目的地的最快路线。 程序的首个版本只能规划公路路线。 驾车旅行的人们对此非常满意。 但很显然, 并非所有人都会在度假时开车。 因此你在下次更新时添加了规划步行路线的功能。 此后, 你又添加了规划公共交通路线的功能。 而这只是个开始。 不久后, 你又要为骑行者规划路线。 又过了一段时间, 你又要为游览城市中的所有景点规划路线。 尽管从商业角度来看, 这款应用非常成功, 但其技术部分却让你非常头疼: 每次添加新的路线规划算法后, 导游应用中主要类的体积就会增加一倍。 终于在某个时候, 你觉得自己没法继续维护这堆代码了。...
行为模式-状态模式
https://refactoringguru.cn/design-patterns/state 行为模式-状态模式亦称: State 意图状态模式是一种行为设计模式, 让你能在一个对象的内部状态变化时改变其行为, 使其看上去就像改变了自身所属的类一样。 问题状态模式与有限状态机的概念紧密相关。 其主要思想是程序在任意时刻仅可处于几种有限的状态中。 在任何一个特定状态中, 程序的行为都不相同, 且可瞬间从一个状态切换到另一个状态。 不过, 根据当前状态, 程序可能会切换到另外一种状态, 也可能会保持当前状态不变。 这些数量有限且预先定义的状态切换规则被称为转移。 你还可将该方法应用在对象上。 假如你有一个 文档Document类。 文档可能会处于 草稿Draft 、 审阅中Moderation和 已发布Published三种状态中的一种。 文档的 publish发布方法在不同状态下的行为略有不同: 处于 草稿状态时, 它会将文档转移到审阅中状态。 处于 审阅中状态时, 如果当前用户是管理员, 它会公开发布文档。 处于 已发布状态时, 它不会进行任何操作。 状态机...
行为模式-观察者模式
https://refactoringguru.cn/design-patterns/observer 行为模式-观察者模式亦称: 事件订阅者、监听者、Event-Subscriber、Listener、Observer 意图观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。 问题假如你有两种类型的对象: 顾客和 商店 。 顾客对某个特定品牌的产品非常感兴趣 (例如最新型号的 iPhone 手机), 而该产品很快将会在商店里出售。 顾客可以每天来商店看看产品是否到货。 但如果商品尚未到货时, 绝大多数来到商店的顾客都会空手而归。 另一方面, 每次新产品到货时, 商店可以向所有顾客发送邮件 (可能会被视为垃圾邮件)。 这样, 部分顾客就无需反复前往商店了, 但也可能会惹恼对新产品没有兴趣的其他顾客。 我们似乎遇到了一个矛盾: 要么让顾客浪费时间检查产品是否到货, 要么让商店浪费资源去通知没有需求的顾客。 解决方案拥有一些值得关注的状态的对象通常被称为目标, 由于它要将自身的状态改变通知给其他对象, 我们也将...
行为模式-备忘录模式
https://refactoringguru.cn/design-patterns/memento 行为模式-备忘录模式亦称: 快照、Snapshot、Memento 意图备忘录模式是一种行为设计模式, 允许在不暴露对象实现细节的情况下保存和恢复对象之前的状态。 问题假如你正在开发一款文字编辑器应用程序。 除了简单的文字编辑功能外, 编辑器中还要有设置文本格式和插入内嵌图片等功能。 后来, 你决定让用户能撤销施加在文本上的任何操作。 这项功能在过去几年里变得十分普遍, 因此用户期待任何程序都有这项功能。 你选择采用直接的方式来实现该功能: 程序在执行任何操作前会记录所有的对象状态, 并将其保存下来。 当用户此后需要撤销某个操作时, 程序将从历史记录中获取最近的快照, 然后使用它来恢复所有对象的状态。 让我们来思考一下这些状态快照。 首先, 到底该如何生成一个快照呢? 很可能你会需要遍历对象的所有成员变量并将其数值复制保存。 但只有当对象对其内容没有严格访问权限限制的情况下, 你才能使用该方式。 不过很遗憾, 绝大部分对象会使用私有成员变量来存储重要数据, 这样别人就无...
行为模式-中介者模式
https://refactoringguru.cn/design-patterns/mediator 行为模式-中介者模式亦称: 调解人、控制器、Intermediary、Controller、Mediator 意图中介者模式是一种行为设计模式, 能让你减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作。 问题假如你有一个创建和修改客户资料的对话框, 它由各种控件组成, 例如文本框 (TextField)、 复选框 (Checkbox) 和按钮 (Button) 等。 某些表单元素可能会直接进行互动。 例如, 选中 “我有一只狗” 复选框后可能会显示一个隐藏文本框用于输入狗狗的名字。 另一个例子是提交按钮必须在保存数据前校验所有输入内容。 如果直接在表单元素代码中实现业务逻辑, 你将很难在程序其他表单中复用这些元素类。 例如, 由于复选框类与狗狗的文本框相耦合, 所以将无法在其他表单中使用它。 你要么使用渲染资料表单时用到的所有类, 要么一个都不用。 解决方案中介者模式建议你停止组件之间的直接交流并使其相互独立。...
行为模式-迭代器模式
https://refactoringguru.cn/design-patterns/iterator 行为模式-迭代器模式亦称: Iterator 意图迭代器模式是一种行为设计模式, 让你能在不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素。 问题集合是编程中最常使用的数据类型之一。 尽管如此, 集合只是一组对象的容器而已。 大部分集合使用简单列表存储元素。 但有些集合还会使用栈、 树、 图和其他复杂的数据结构。 无论集合的构成方式如何, 它都必须提供某种访问元素的方式, 便于其他代码使用其中的元素。 集合应提供一种能够遍历元素的方式, 且保证它不会周而复始地访问同一个元素。 如果你的集合基于列表, 那么这项工作听上去仿佛很简单。 但如何遍历复杂数据结构 (例如树) 中的元素呢? 例如, 今天你需要使用深度优先算法来遍历树结构, 明天可能会需要广度优先算法; 下周则可能会需要其他方式 (比如随机存取树中的元素)。 不断向集合中添加遍历算法会模糊其 “高效存储数据” 的主要职责。 此外, 有些算法可能是根据特定应用订制的, 将其加入泛型集合类...
行为模式-命令模式
https://refactoringguru.cn/design-patterns/command 行为模式-命令模式亦称: 动作、事务、Action、Transaction、Command 意图命令模式是一种行为设计模式, 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中, 且能实现可撤销操作。 问题假如你正在开发一款新的文字编辑器, 当前的任务是创建一个包含多个按钮的工具栏, 并让每个按钮对应编辑器的不同操作。 你创建了一个非常简洁的 按钮类, 它不仅可用于生成工具栏上的按钮, 还可用于生成各种对话框的通用按钮。 尽管所有按钮看上去都很相似, 但它们可以完成不同的操作 (打开、 保存、 打印和应用等)。 你会在哪里放置这些按钮的点击处理代码呢? 最简单的解决方案是在使用按钮的每个地方都创建大量的子类。 这些子类中包含按钮点击后必须执行的代码。 你很快就意识到这种方式有严重缺陷。 首先, 你创建了大量的子类, 当每次修改基类 按钮时, 你都有可能需要修改所有子类的代码。 简单来说, G...