设计模式
- 设计模式
- 2024-05-27
- 176热度
- 0评论
一、设计模式概念
1.1 设计模式是什么
设计模式是软件设计中常见问题的典型解决方案,他们就像能根据需求进行调整的预制蓝图,可用于解决代码中反复出现的设计问题.设计模式就是问题反复出现,然后通过设计来解决问题,然后记录下来解决方式,进行总结就成为了设计模式.
设计模式:在某个场景下,针对某类问题的某种通用的解决方案.
-
场景:项目所在的环境
-
问题:约束条件,项目目标等
-
解决方案:通用、可复用的设计,解决约束达到的目标
1.2 设计模式的作用
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
- 可重用性:使功能相同的代码,不需要多次编写
- 可读性:编程规范性,在项目开发中,便于其他程序员的阅读和理解
- 可扩展性:当需要添加新的功能时,对原来的功能没有影响
- 高内聚低耦合:一个模块内各个元素彼此结合的紧密程度高(高内聚),不同的模块之间独立存在(低耦合)
二、设计模式的分类
2.1 根据目的分类
设计模式根据目的分类(模式用来做什么的)一共分为三大类,分别是创建型模式、结构型模式、行为型模式.
- 创建型模式:针对对象实例化的模式,用于解耦对象的实例化过程
- 结构型模式:将对象和类组装成较大的结构,并同时保持结构的灵活性和高效性
- 行为型模式:对象之间如何高效沟通和职责划分.
2.2 根据范围分类
设计模式根据范围分类(模式主要用于处理类之间的关系还是处理对象之间的关系)可分为两大类,分别是类模式和对象模式
- 类模式:处理类和子类之间的关系,这些关系通过继承建立,在编译时就被确定下来
- 对象模式:处理对象之间的关系,这些关系在随时改变,更具有动态性
三、 设计模式的简单概述
3.1 创建者模式
- 单例模式:某个静态类只有一个实例,且提供一个全局的访问点.
- 工厂模式:提供一个创建对象的方法,让其子类决定需要实例化哪个工厂类.
- 抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类.
- 建造者模式:将一个复杂对象的构建与它的表示分离,使同样的构建过程可以创建不同的表示.
- 原型模式:通过原型实例指定创建对象的类型,通过复制这个原型来创建新的对象.
3.2 结构型模式
- 适配器模式:将一个类的接口转换为客户希望的另一个接口,让那些接口不兼容的类可以一起工作.
- 桥接模式:将抽象部分与它实现的部分解耦,使两者都可以独立的变化
- 组合模式:组合多个对象形成树状结构以表示具有部分-整体关系的层次结构.
- 装饰模式:动态地给对象增加一些额外的职责(拓展功能)
- 外观模式:为子系统中的一组接口提供了一个统一的入口.
- 享元模式:通过共享技术有效地支持大量的细粒度对象的复用.
- 代理模式:给对象提供一个代理或占位符,并由代理对象来控制对原对象的访问
3.3 行为者模式
- 责任链模式:一个请求需要在多个对象之间传递,每个对象都可能处理该请求或者将其传递给下一个对象。
- 命令模式:将请求封装成一个所有信息独立的对象,可以根据不同的请求对方法进行参数化、延迟请求执行或将其放入队列中。
- 解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器用来解释语言中的句子。
- 迭代器模式:提供一个方法顺序访问聚合对象的各个元素,而又不用暴露该对象的内部表示。
- 中介者模式:定义一个中间对象来封装一系列对象之间的交互,中间者可以使个对象之间不需要显式地相互应用,从而使其耦合松散,可以独立地改变它们之间地交互。
- 备忘录模式:在不破坏封装地前提下捕获一个对象的内部状态,并在对象之外保存该状态,可以在以后恢复对象之前的状态。
- 观察者模式:定义了对象之间的一个一对多的依赖关系,当一个被依赖的对象状态发生改变时,依赖的对象状态也会随之改变。
- 状态模式:让一个对象的内部状态发生变化时改变其行为,使其看上去改变了自身所属的类一样。
- 策略模式:定义一系列算法,将每个算法给封装起来,并让它们能够相互替换,算法的变化不会影响到使用算法的客户。
- 模板模式:定义一个操作中方法框架,允许子类在不修改结构的情况下重新方法的特定步骤。
- 访问者模式:表示一个作用于某对象结构的各个元素的操作。
四、 设计模式的六大原则
4.1 单一职责原则
定义:一个对象应该只包含单一职责,并且该职责被完整地封装在一个类中。
优点:
-
可以降低类的复杂度,一个类只负责一项职责。
-
提高类的可读性,提高系统的可维护性。
-
变更引起的风险降低,高类聚,低耦合。
4.2 开放封闭原则
定义:一个软件实体(类、模块、函数)应该对外扩展,对修改关闭。
关键点:用抽象构建框架,用实现扩展细节
其实,剩下的那5项原则,恰恰是告诉我们用抽象构建框架,用实现扩展细节的注意事项而已:
- 单一职责原则告诉我们实现类要职责单一;
- 里氏替换原则告诉我们不要破坏继承体系;
- 依赖倒置原则告诉我们要面向接口编程;
- 接口隔离原则告诉我们在设计接口的时候要精简单一;
- 迪米特法则告诉我们要降低耦合。
- 开闭原则是总纲,他告诉我们要对扩展开放,对修改关闭。
4.3 里氏替换原则
定义:所有引用基类的地方必须能够透明地使用其子类地对象
关键点:
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
- 子类可以增加自己特有的方法。
- 父类设计为抽象类或者接口,让子类继承父类或实现父类接口
4.4 依赖倒置原则
定义:高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象不应该依赖细节,细节应该依赖于抽象,
关键点:针对接口编程,不要针对实现编程。
优点:
- 降低类之间的耦合性。
- 提高系统的稳定性,降低修改程序造成的风险。
4.5 接口隔离原则
定义:客户端不应该依赖它不需要的接口。
关键点:
- 接口尽量小,但是要有限度,如果过小会导致系统接口泛滥,不利于维护
- 为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。
4.6 迪米特原则(最少知道原则)
定义:一个对象应该对其他对象保持最少的了解。即一个类对自己依赖的类知道的越少越好(只与直接的朋友通信)
每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。
耦合的方式很多,如依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。