# easy_design **Repository Path**: hhdproject/easy_design ## Basic Information - **Project Name**: easy_design - **Description**: 23种设计模式 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-03-25 - **Last Updated**: 2024-03-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 本项目主要讲解了不同语言实现 软件开发过程中常见的23种设计模式 # 设计模式 ## 1 创建型设计模式 ### 1.1 简单工厂模式 > Go语言是没有构造函数的,一般会采用 NewXXX 的方式来创建对象或接口。当返回接口的时候,就是简单工厂模式。 > - 比如说有一个汽车代工厂,它可以为各个品牌生产汽车: ### 1.2 工厂方法模式 > 抽象工厂模式(Abstract Factory Pattern)是由一个超级工厂创建其它的工厂,也可以称它为工厂的工厂。抽象工厂模式中的接口注意负责创建一个对象的工厂。 > - 简单工厂模式和抽象工厂模式最大的区别其实就是:简单工厂模式是生产单个同类型的不同产品,例如戴尔电脑,苹果电脑。而抽象工厂模式生产的是多个不同类型的不同产品,所以必须将共同点抽象出来,例如戴尔CPU,苹果CPU,抽象的接口就是CPU。戴尔GPU,苹果GPU,抽象的接口就是GPU。这也是为了遵守面向对象的原则之一,面向接口编程而不是内容编程。 ### 1.3 创建者模式 >建造者模式使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式。还可以通过返回自身进行链式调用。 > - 如经常使用的SQLBuilder就属于这种,一步步构建成一个完整的SQL ```sql err := engine.Where(builder.NotIn("a", 1, 2).And(builder.In("b", "c", "d", "e"))).Find(&users) -- SELECT id, name ... FROM user WHERE a NOT IN (?, ?) AND b IN (?, ?, ?) ``` 建造者模式由产品角色、抽象建造者、具体建造者: 产品角色:由多个部件组成的对象,由具体建造者来创建各个部件。 抽象建造者:提供创建各个部件的抽象接口。 具体建造者:实现抽象建造者的接口,完成各部件的具体创建方法。 ### 1.4 原型模式:创建当前对象的克隆 > 原型模式用于创建当前对象的克隆:通过拷贝当前对象创建新的对象。原型模式一般用于创建复杂的实例,这样使用其它更简洁高效。 ### 1.5 单例模式 > 一个类只允许创建一个实例,那这个类就是一个单例类,这种模式就叫单例模式。 > - 从业务上来讲,有些数据在系统中应该只保存一份,如配置初始化、数据库连接初始化等,这时就比较适合单例模式。 > - 单例模式有 饿汉式 和 懒汉式 两种实现。 ## 2 结构型设计模式 ### 2.1 外观模式:"一键完成" > 外观模式又叫门面模式,它通过定义一个高层接口,来隐藏子系统的复杂性,为外界提供一个一致的接口。 > - 我们假设一程序员下班回到家想要洗澡,那么它首先需要打开灯、热水器、空调,边洗澡还想边看个电视,一步步完成这些操作步骤是有点多,我们这个是个聪明的程序员,他做了智能家居改装,这样就只需要一键就可以完成所有操作。 ### 2.2 适配器模式:"充电器适配“ > 适配器模式用于将一个类的接口转换为调用方希望的另外一个接口,使得原本不兼容的接口也可以一起工作。 举个常见的例子:如果去美国旅游,那随身携带的国内的电器插头就无法使用,因为国内和美国的电压标准不同,这是就需要一个适配器。 ### 2.3 代理模式:"nginx" > 常用的 nginx、haproxy 等的反向代理服务器正是基于这一原理实现,代理服务器提供了对外的访问接口,内部则根据各种规则路由到不同的服务器上。 > - 像gin、echo等web框架中的中间件的实现的切面动作,可以在执行到我们代码逻辑的前后增加记录日志、安全校验等动作,由中间件决定是否要调用我们的代码。 ### 2.4 享元模式:"内存缓存,防止重复创建或读取" > 享元模式主要用于减少创建对象的数量,以减少内存的占用并提升性能。它通过重用现有的同类对象,如果没有找到匹配的对象就创建新的对象。享元模式通常会使用一个享元工厂来负责维护享元池来存储具有相同内部状态的享元对象。 > - 实际应用中享元模式注意用于缓存,客户端重复请求不必每次都去查询数据库或读取文件,而是直接返回内存中缓存的数据。 > - 常用的场景是数据库连接池 ### 2.5 装饰模式:"给游戏角色添加装备:武器+皮肤等" > 例:给一个游戏角色添加武器:手枪,添加皮肤 装饰器模式有4个角色: 抽象构件(Component): 被装饰对象的抽象。 具体构件(Concrete Component):实现抽象构件,是被装饰的对象。 抽象装饰器(Decorator): 关联抽象构件,可通过具体装饰器装饰具体构件。 具体装饰器(Concrete Decorator): 实现抽象装饰器的方法,并对具体构件进行装饰,即为具体构件对象添加新的职责。 ### 2.6 桥模式:"汽车与发动机" > Bridge:桥接模式将抽象部分与它的实现部分分离,使功能实现独立于接口。 > - 我们以汽车为例, 汽车可以安装、切换不同的发动机,汽车是不需要实现发动接口的,只需要在汽车上装载一个发动机,然后汽车可直接通过调用发动机来启动它,这样汽车和发动机就实现进行分离,减少了耦合。 ### 2.7 组合模式:"窗口由按钮、logo组成" > Composite:组合模式常用于将对象组合成树形结构,用于统一叶子节点和树节点访问,并且可以用于应用某一操作到所有子节点 > 在计算机文件系统中,文件夹里面又可以放入文件和文件夹,文件夹和文件就组成了一种递归结构和容器结构。虽然它们的属性有些不同,我们依然可以把文件夹和文件看作同一种类型的对象,它们都属于文件系统中的一个条目,这样可以方便我们递归处理。 > - 例如:我们画一个窗口,窗口内由各个组件,Logo、登录按钮、取消按钮等 ## 3 行为型设计模式 ### 3.1 中介者模式:"房屋中介" > Mediator:中介者模式是用来降低多个对象和类之间的通信复杂性,该模式会限制对象之间的直接交互,能减少对象之间混乱无序的依赖关系。中介者模式提供了一个中介类,这个类用来处理不同类之间的通信,使各个类通过一个中介者对象进行合作,以实现松耦合,使代码更易于维护。不过,由于中介者对象封装了各个类之间的交互,会使中介者本身的变的复杂。 > - 在租房的场景中,没有中介之前,租房者要东奔西跑去找各个房东。有了中介后,房东会把出租房登记倒中介那里,租房者只需要去找中介就可以租到各种你想要的房子。也就是把多对多的复杂关系,变成了多对一的关系。 ### 3.2 观察者模式:"发布订阅" > Observer:观察者模式,又称发布订阅模式,比如对象存在一对多关系,当其中某个对象被修改时会自动通知依赖的其它对象。 > - 比如订阅了某个公众号,当公众号有新文章发布时,会自动推送消息到你的手机上。 ### 3.3 命令模式:"小饭馆吃饭:服务员倒水、厨师做饭、服务员结账" > Command:命令模式是一种数据驱动的设计模式,属于行为型的模式。它将请求以命令的形式包裹在对象中,并传递给调用对象,调用对象可以用自己的逻辑处理该对象。 > 现在假设你去一家小饭馆吃饭: > - 先让服务员倒一杯水,这里就发出一个倒水的命令:PourWaterCommand,接收对象是服务员 > - 然后点了一道菜,让厨师去做,发出一个做饭的命令:CookCommand,接收对象是厨师 > - 吃过饭后,你又发出一个结账的命令:CheckoutCommand,接收对象是服务员 ### 3.4 迭代器模式:"集合元素的遍历" > Iterator:迭代器模式提供了一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该集合的内部对象。最常见的迭代器模式就是循环了 > - 我们可以从迭代器会依次取出元素,当没有元素的时候,迭代终止。 > - HasNext() bool > - Current() interface{} ### 3.5 模版方法模式:"抽象类定义方法,子类实现" > Template:在模板模式中,定义一个算法的骨架,然后抽象出来,公开定义执行它的方法模板,使得子类可以不用改变算法的结构就可以从定义该算法的某些特定步骤。模板方法的核心就在于定义了父类一个算法的骨架,子类实现某些具体的细节。 ### 3.6 策略模式:"电商-不同会员优惠力度不同" > Strategy:在策略模式中,一个类的行为可以根据算法在运行时更改。一个完整的策略模式需要创建出各个策略对象和使用策略的上下文。 > 电商网站购物车结算为例,可以针对普通用户、会员又不同的折扣,还可以有满减的活动策略。 ### 3.7 状态模式:"QQ:在线、离线、忙碌中" > State:状态模式经常应用于带有状态的对象中,类的行为是基于它的状态改变的,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变。 > 什么是状态?以常用的QQ为例,一般有这几种状态: > - 在线 > - 离线 > - 正在登录中 > - 忙碌中 如何表示状态呢?一般会用枚举表示不同的状态,但是不同的状态需要处理不同的行为: 如果状态越多,需要处理的逻辑分支就越多。使用状态模式的目的就是为了把一大串的if...else...逻辑拆分到不同的状态类中,这样如果将来增加状态会更容易处理。 ### 3.8 备忘录模式:"文本编辑器ctrl+Z撤销、ctrl+Y恢复" > Memento:备忘录模式用于保存一个对象的某个状态,以便在适当的时候恢复对象。 > - 几乎所有的软件都用到了备忘录模式,像常用的文本编辑器,我们将文本保存到文件,可以通过Ctrl+Z撤销操作恢复到上次操作的状态,关闭文档后再次打开也是恢复到上次编辑时的状态。类似的还有游戏的存档功能、浏览器的前进后退。 ### 3.9 解释器模式:"SQL解析" > Interpreter:解释器模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式常被用在SQL解析、代码编译器、符号处理引擎等,它是一种针对特定问题而设计的解决方案。 > 例如给计算器一个字符串的表达式 "1+10",计算器要先把数字和操作符解析出来,然后按照操作符的优先级,再由不同的操作符解释器去处理 ### 3.10 职责链模式:"刑事案件处理,如果处理不了层层上报" > Chain:责任链模式为请求创建了一个接受者对象的链,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者。职责链模式用于分离不同职责,并且动态组合相关职责。 > Request ——> ProcessorA ——> ProcessorB ——> ProcessorC ——> ... > 一个刑事案件,如果乡镇上处理不了就交给市区,如果市区处理不了就交给省,如果省处理不了就交给国家... > - Handle > - NextHandler ### 3.11 访问者模式:"不同环境打印不同内容" > Visitor:访问者模式是一种操作一组对象的操作,它的目的是不改变对象的定义,但可以新增不同的访问者来定义新的操作。访问者的核心思想是为了访问比较复杂的数据结构,不去改变原数据结构,而是把对数据的操作抽象出来,在访问的过程中以回调形式在访问者中处理逻辑操作。如果要新增一组操作,那么只需要增加一个新的访问者。 > 假如一个对象的方法,我们要在生产环境和测试环境中打印处不同的内容,就可以使用访问者模式,把打印内容抽象出来,然后在不同的环境中,通过不同的访问者(ProductionVisitor、TestingVisitor)来处理打印内容。