三、设计模式

三、设计模式

大部分设计模式要解决的都是代码的可扩展性问题
开发初期,除非特别必须,我们一定不要过度设计,应用复杂的设计模式。而是当代码出现问题的时候,我们再针对问题,应用原则和模式进行重构。这样就能有效避免前期的过度设计

设计模式要干的事情就是解耦。
创建型模式是将创建和使用代码解耦,
结构型模式是将不同功能代码解耦,
行为型模式是将不同的行为代码解耦

1. 创建型

常用的有:单例模式、工厂模式(工厂方法和抽象工厂)、建造者模式。
不常用的有:原型模式

创建型模式主要解决对象的创建问题,封装复杂的创建过程,解耦对象的创建代码和使用代码。

  • 单例模式用来创建全局唯一的对象。
    经典的实现方式:

    饿汉式、懒汉式、双重检测、静态内部类、枚举

    替代单例的解决方案:

    通过工厂模式、IOC 容器来保证全局唯一性。

  • 工厂模式用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。如果创建对象的逻辑并不复杂,那直接通过 new
    来创建对象就可以了,不需要使用工厂模式。当创建逻辑比较复杂,是一个“大工程”的时候,考虑使用工厂模式,封装对象的创建过程,将对象的创建和使用相分离。

    • 工厂模式非常经典的应用场景:依赖注入框架(比如 Spring IOC),它用来集中创建、组装、管理对象,跟具体业务代码解耦,让程序员聚焦在业务代码的开发上。


      判断要不要使用工厂模式的参考标准:

    1、封装变化:创建逻辑有可能变化,封装成工厂类之后,创建逻辑的变更对调用者透明。
    2、代码复用:创建代码抽离到独立的工厂类之后可以复用。
    3、隔离复杂性:封装复杂的创建逻辑,调用者无需了解如何创建对象。
    4、控制复杂度:将创建代码抽离出来,让原本的函数或类职责更单一,代码更简洁。

  • 建造者模式是用来创建复杂对象,可以通过设置不同的可选参数,“定制化”地创建不同的对象。

    • 应用场景:

    1、类的必填属性放到构造函数中,强制创建对象的时候就设置。如果必填的属性有很多,把这些必填属性都放到构造函数中设置,那构造函数就又会出现参数列表很长的问题。如果我们把必填属性通过 set() 方法设置,那校验这些必填属性是否已经填写的逻辑就无处安放了。
    2、类的属性之间有一定地依赖关系或者约束条件,使用构造函数配合 set() 方法的设计思路,那这些依赖关系或约束条件的校验逻辑就无处安放了。
    3、创建不可变对象,对象在创建好之后,就不能再修改内部的属性值,要实现这个功能,就不能在类中暴露 set() 方法。构造函数配合 set() 方法来设置属性值的方式就不适用了。

  • 原型模式针对创建成本比较大的对象,利用对已有对象进行复制的方式进行创建,以达到节省创建时间的目的。

2. 结构型

常用的有:代理模式、桥接模式、装饰者模式、适配器模式。
不常用的有:门面模式、组合模式、享元模式。

结构型设计模式主要解决“类或对象的组合或组装”问题

  • 代理模式:代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,而非加强功能,这是它跟装饰器模式最大地不同。

    • 应用场景:

      非功能性需求,比如:监控、统计、鉴权、限流、事务、幂等、日志、RPC、缓存等应用场景中。

  • 桥接模式:桥接模式的目的是将接口部分和实现部分分离,从而让它们可以较为容易、也相对独立地加以改变。

    接口,指的并非“抽象类”或“接口”,而是被抽象出来的一套“类库”,它只包含 骨架代码,真正的业务逻辑需要委派给定义中的“实现”来完成
    实现,并非“接口的实现类”,而是的一套独立的“类库”。
    抽象”和“实现”独立开发,通过对象之间的组合关系组装在一起。

  • 装饰器模式:装饰者模式在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的嵌套使用。

    主要解决继承关系过于复杂的问题,通过组合来替代继承,给原始类添加增强功 能。
    可以对原始类嵌套使用多个装饰器。装饰器类需要跟原始类继承相同的抽象类或者接口。

  • 适配器模式:适配器模式是一种事后的补救策略。适配器提供跟原始类不同的接口,而代理模式、装饰器模式提供的都是跟原始类相同的接口。

  • 门面模式:通过封装细粒度的接口,提供组合各个细粒度接口的高层次接口,来提高接口的易用性,或者解决性能、分布式事务等问题。

  • 组合模式:用来处理树形结构数据。数据必须能表示成树形结构,将单个对象和组合对象都看作树中的节点,以统一处理逻辑,递归地处理每个子树,依次简化代码实现。

  • 享元模式:前提是享元对象是不可变对象。

3. 行为型

常用的有:观察者模式模板模式策略模式职责链模式迭代器模式
状态模式
不常用的有:访问者模式、备忘录模式、命令模式、解释器模式、中介模式

行为型设计模式主要解决的就是“类或对象之间的交互”问题

  • 观察者模式:将观察者和被观察者代码解耦。

    小到代码层面的解耦,大到架构层面的系统解耦,再或者一些产品的设计思路,都有这种模式的影子,比如,邮件订阅、RSS Feeds,本质上都是观察者模式。

  • 模板模式:一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。

    两大作用:复用和扩展。其中复用指的是,所有的子类可以复用父类中提供的模 板方法的代码。扩展指的是,框架通过模板模式提供功能扩展点,让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能。

    • 回调跟模板模式具有相同的作用:代码复用和扩展。(JdbcTemplate 就是用了回调)

      回调基于组合关系来实现,模板模式基于继承关系来实现。回调比模板模式更加灵活。

  • 策略模式:解耦策略的定义、创建、使用。
    应用场景:

    1、避免冗长的 if-else 或 switch 分支判断。
    2、提供框架的扩展点
    3、对于复杂代码来说,策略模式还能让其满足开闭原则,添加新策略的时候,最小化、集中化代码改动,减少引入 bug 的风险。

  • 职责链模式:多个处理器依次处理同一个请求。链条上的每个处理器各自承担各自的处理职责
    应用场景:

    实现过滤器、拦截器功能,让框架的使用者在不需要修改框架源码的情况下,添加新地过滤、拦截功能。

  • 迭代器模式:用来遍历集合对象。主要作用是解耦容器代码和遍历代码

  • 状态模式:常用在游戏、工作流引擎等系统开发中。

    由 3 个部分组成:状态、事件、动作。其中,事件也称为转移条件。事件触发状态的转移及动作的执行。不过,动作不是必须的,也可能只转移状态,不执行任何动作。

  • 访问者模式:允许一个或者多个操作应用到一组对象上,设计意图是解耦操作和对象本身,保持类职责单一、满足开闭原则以及应对代码的复杂性。

    对于访问者模式,学习的主要难点在代码实现。而代码实现比较复杂的主要原因是,函数重载在大部分面向对象编程语言中是静态绑定的。也就是说,调用类的哪个重载函数,是在编译期间,由参数的声明类型决定的,而非运行时,根据参数的实际类型决定的。因为代码实现难理解,所以,在项目中应用这种模式,会导致代码的可读性比较差。

  • 备忘录模式:快照模式在不违背封装原则的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便之后恢复对象为先前的状态
    应用场景:

    主要用来防丢失、撤销、恢复等。

  • 命令模式:最核心的实现手段,就是将函数封装成对象。
    应用场景:

    用来控制命令的执行,比如,异步、延迟、排队执行命令、撤销重做命令、存储命令、给命令记录日志等

  • 解释器模式:核心思想,就是将语法解析的工作拆分到各个小类中,以此来避免大而全地解析类。一般的做法是,将语法规则拆分一些小的独立的单元,然后对每个单元进行解析,最终合并为对整个语法规则的解析。

  • 中介模式:设计思想跟中间层很像,通过引入中介这个中间层,将一组对象之间的交互关系从多对多(网状关系)转换为一对多(星状关系)。从而最小化对象之间的交互关系,降低了代码的复杂度,提高了代码的可读性和可维护性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值