设计模式全解(含代码实例)
目录
- 设计模式概念
- 耦合与解耦
- 常见-5种
- 全部-23种
- 创建型模式(Creational Patterns)
- ==单例模式==(Singleton Pattern)
- ==工厂方法模式==(Factory Method Pattern):
- 抽象工厂模式(Abstract Factory Pattern):
- 建造者模式(Builder Pattern):
- 原型模式(Prototype Pattern):
- 结构型模式(Structural Patterns)
- 适配器模式(Adapter Pattern):
- 桥接模式(Bridge Pattern):
- 组合模式(Composite Pattern):
- ==装饰器模式==(Decorator Pattern):
- 外观模式(Facade Pattern):
- 享元模式(Flyweight Pattern):
- 代理模式(Proxy Pattern):
- 行为型模式(Behavioral Patterns)
- 责任链模式(Chain of Responsibility Pattern):
- 命令模式(Command Pattern):
- 解释器模式(Interpreter Pattern):
- 迭代器模式(Iterator Pattern):
- 中介者模式(Mediator Pattern):
- 备忘录模式(Memento Pattern):
- ==观察者模式==(Observer Pattern):
- 状态模式(State Pattern):
- ==策略模式==(Strategy Pattern):
- 模板方法模式(Template Method Pattern):
- 访问者模式(Visitor Pattern):
设计模式概念
设计模式(Design Pattern)是经过反复验证的、用于解决软件设计中常见问题的通用解决方案。它们并不是直接可以复制的代码,而是一些解决问题的思路和方法。设计模式主要目标是提高软件的可重用性、可维护性、扩展性和解耦性。
设计模式的核心思想是总结和提炼软件开发中的最佳实践,帮助开发人员在面对具体问题时能够避免重复造轮子。
耦合与解耦
耦合是指两个或两个以上的体系或两种运动形式间通过相互作用而彼此影响以至联合起来的现象。在软件工程中,对象之间的耦合度就是对象之间的依赖性。对象之间的耦合越高,维护成本越高,因此对象的设计应使类和构件之间的耦合最小。
解耦,字面意思就是解除耦合关系。让数据模型,业务逻辑和视图显示三层之间彼此降低耦合,把关联依赖降到最低,而不至于牵一发而动全身。原则就是A功能的代码不要写在B的功能代码中,如果两者之间需要交互,可以通过接口,通过消息,甚至可以引入框架,但总之就是不要直接交叉写。
代表:观察者模式,观察者模式存在的意义就是「解耦」,它使观察者和被观察者的逻辑不再搅在一起,而是彼此独立、互不依赖。比如网易新闻的夜间模式,当用户切换成夜间模式之后,被观察者会通知所有的观察者「设置改变了,大家快蒙上遮罩吧」。QQ消息推送来了之后,既要在通知栏上弹个推送,又要在桌面上标个小红点,也是观察者与被观察者的巧妙配合。
常见-5种
最常见的设计模式:单例模式、工厂方法模式、观察者模式、策略模式和装饰器模式。
全部-23种
总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
创建型模式(Creational Patterns)
主要处理对象的创建问题,确保对象创建过程的灵活性,提供一些通用的方式来创建对象。
单例模式(Singleton Pattern)
确保类只有一个实例,并提供全局访问点。
适用于控制某些资源(如数据库连接、日志管理等)的共享。
应用场景表现在:全局状态管理(如Redux中的Store)。数据库连接池。日志记录器。
工厂方法模式(Factory Method Pattern):
定义一个创建对象的接口,让子类决定实例化哪个类。
适用于需要创建不同类型的对象,但不希望直接使用 new 来实例化时。
抽象工厂模式(Abstract Factory Pattern):
提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。常用于跨平台的 UI 库等。
建造者模式(Builder Pattern):
使用多个简单的对象一步步构建成一个复杂的对象。
适用于对象构建过程非常复杂或者有多个可选项的情况。
原型模式(Prototype Pattern):
通过复制现有的对象来创建新的对象,而不是通过构造函数来实例化。
适用于创建成本较高或需要大量相似对象的情况。
结构型模式(Structural Patterns)
关注如何将类和对象组合成更大的结构,保证结构的灵活性和效率。
适配器模式(Adapter Pattern):
将一个类的接口转换成客户端期望的另一种接口,使原本由于接口不兼容而不能一起工作的类可以一起工作。
适用于需要将现有类库或系统与其他接口兼容时。
一般应用场景表现在:兼容旧代码。集成第三方库。
桥接模式(Bridge Pattern):
将抽象部分与实现部分分离,使得两者可以独立变化。
适用于希望将抽象层和实现层解耦的场景。
组合模式(Composite Pattern):
将对象组合成树形结构以表示“部分-整体”的层次结构。
适用于需要处理树形结构数据的场景,如文件系统。
装饰器模式(Decorator Pattern):
动态地给一个对象添加额外的职责,不影响其他对象。
适用于增强或改变对象功能,但不希望改变原有对象的情况。
一般应用场景表现在:扩展对象功能(如添加日志、缓存)。动态添加属性或方法。
外观模式(Facade Pattern):
提供一个统一的接口,用来访问子系统中的一组接口,简化客户端与子系统的交互。
适用于复杂系统的简化接口层设计。
享元模式(Flyweight Pattern):
通过共享对象来减少内存使用,尤其是大量相似的对象。
适用于内存密集型的系统,特别是在大量相似对象存在时。
代理模式(Proxy Pattern):
为其他对象提供代理,以控制对该对象的访问。
适用于需要控制访问的场景,如虚拟代理、保护代理等。
一般应用场景表现在:延迟加载(如图片懒加载)。访问控制(如权限验证)。缓存代理。
行为型模式(Behavioral Patterns)
关注对象之间的交互和责任分配,确保对象之间能够有效协作。
责任链模式(Chain of Responsibility Pattern):
使多个对象都有机会处理请求,从而避免请求发送者与接收者之间的耦合关系。
适用于处理多个处理环节的场景,如请求处理、日志记录等。
命令模式(Command Pattern):
将请求封装为一个对象,从而使用户能够传递不同的请求、队列或日志请求,并支持可撤销的操作。
适用于实现操作队列、撤销操作等功能。
一般应用场景表现在:撤销/重做功能。任务队列。宏命令。
解释器模式(Interpreter Pattern):
给定一个语言的语法,定义一个解释器来解释语言中的句子。
适用于需要解析和解释的应用,如正则表达式引擎。
迭代器模式(Iterator Pattern):
提供一种方法顺序访问集合对象中的每个元素,而不暴露集合对象的内部结构。
适用于需要遍历集合类对象的场景。
中介者模式(Mediator Pattern):
用一个中介对象来封装一系列对象之间的交互,使得对象不需要显示地引用其他对象,从而使得松散耦合。
适用于复杂对象交互的场景,如 UI 元素交互。
备忘录模式(Memento Pattern):
捕获一个对象的内部状态,并在必要时恢复该状态,而不暴露该对象的实现细节。
适用于需要保存和恢复对象状态的场景,如撤销操作。
观察者模式(Observer Pattern):
定义对象之间的一对多依赖关系,当一个对象状态改变时,所有依赖于它的对象都会得到通知并自动更新。
适用于事件处理和数据绑定的场景。
一般应用场景表现在:事件处理系统。数据绑定(如Vue.js的响应式系统)。发布-订阅系统。
状态模式(State Pattern):
允许对象在其内部状态改变时改变其行为,表现出不同的行为。
适用于状态转换较为复杂的场景,如工作流、状态机等。
一般应用场景表现在:状态机(如订单状态),游戏角色状态。
策略模式(Strategy Pattern):
定义一系列算法,并使它们可以相互替换,算法的使用可以在运行时决定。
适用于有多种算法可以选择的场景,且希望通过选择不同的算法来解决问题。
一般应用场景表现在:动态选择算法(如排序算法)。表单验证规则。支付方式选择。
模板方法模式(Template Method Pattern):
定义一个操作中的算法骨架,允许子类在不改变算法结构的情况下重新定义算法的某些步骤。
适用于需要一些步骤固定而其他步骤可以灵活变化的场景。
一般应用场景表现在:框架设计。算法复用。
访问者模式(Visitor Pattern):
通过在不改变元素类的前提下,增加新的操作来访问元素对象。
适用于需要对一组对象执行不同操作,并且不想修改这些对象的情况。