【零】Java设计模式[前置] - 设计模式七大原则

前言

一、前置知识点

今天在学习设计模式的时候,视频在讲到原型设计模式的提到scope为prototype的bean的问题的时候,弹幕里提到一个问题:bean的scope为prototype的时候,它到底归不归Spring容器管理
所以先了解下这个问题

1.1 bean的作用范围(就讲讲有分歧的两个,具体查看参考资料)
1.1.1 singleton

当一个 bean 的作用域为 singleton,那么Spring IoC容器中只会存在一个共享的 bean 实例,并且所有对 bean 的请求,只要 id 与该 bean 定义相匹配,则只会返回bean的同一实例。
singleton 是单例类型(对应于单例模式),就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,但我们可以指定Bean节点的 lazy-init=”true” 来延迟初始化bean,这时候,只有在第一次获取bean时才会初始化bean,即第一次请求该bean时才初始化。
每次获取到的对象都是同一个对象。注意,singleton 作用域是Spring中的缺省作用域。要在XML中将 bean 定义成 singleton ,可以这样配置:
也可以通过 @Scope 注解(它可以显示指定bean的作用范围。)的方式
@Service@Scope(“singleton”)public class ServiceImpl{}

1.1.2 prototype

每次请求都会创建一个新的 bean 实例
当一个bean的作用域为 prototype,表示一个 bean 定义对应多个对象实例。
prototype 作用域的 bean 会导致在每次对该 bean 请求(将其注入到另一个 bean 中,或者以程序的方式调用容器的 getBean() 方法)时都会创建一个新的 bean 实例。prototype 是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象
对有状态的 bean 应该使用 prototype 作用域,而对无状态的 bean 则应该使用 singleton 作用域。
在 XML 中将 bean 定义成 prototype
或者
通过 @Scope 注解的方式实现

1.1.3 五种作用域(参考资料截图)

在这里插入图片描述

五种作用域中,request、session和global session三种作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于 web 的 Spring ApplicationContext 环境。

1.2 scope为protype的bean,spring容器到底管不管

其他的作用域相比,Spring不会完全管理原型Bean的生命周期:

Spring容器只会初始化配置以及装载这些Bean,传递给Client。

但是之后就不会再去管原型Bean之后的动作了。

也就是说,初始化生命周期回调方法在所有作用域的Bean是都会调用的,但是销毁生命周期回调方法在原型(prototype)Bean是不会调用的

所以,客户端代码必须注意清理原型Bean以及释放原型Bean所持有的一些资源。

可以通过使用自定义的bean post-processor来让Spring释放掉原型Bean所持有的资源。

1.3 单例Bean和单例模式

单例作用域是Spring的默认作用域(bean只是一个上下文的单例),单例模式是设计模式的一种。

单例模式是将一个对象的作用域硬编码,一个ClassLoader只有唯一的一个实例

而Spring的单例作用域,是基于每个容器(org.springframework.context.ApplicationContext),每个Bean只有一个实例(同一Java的类加载器可以有多个ApplicationContext)

二、 设计模式七大原则

2.1 单一职责原则(保证类的功能统一,减少耦合)
  1. 降低类的复杂性,一个类只维护一项责任
  2. 提高类的可读性和可维护性
  3. 通常情况下,我们应当遵守单一职责原则,优先级别为类 - 方法,优先遵守类的单一职责,如果不方便拆分类(只有类中方法足够少),可先遵守方法的单一职责原则。
2.2 接口隔离原则(保证接口定义精确,减少耦合)

客户端不应该依赖它不需要的接口,即一个类对另一个类的依赖应该建立在最小接口上。
举个例子:
接口interface1有5个方法,1 2 3 4 5,而实现类A要使用1 2 3,类B要使用 3 4 5,然而因为实现接口就要实现它的全部方法,会导致类A和B都会实现2个他不需要的方法,这不符合接口隔离原则。
应该将interface1拆分为独立的几个接口,实现类只实现他们需要的接口(相当于两个类的最小公约数),接口可以分为[1,2] [3] [4,5]实现对应方法的3个接口,这样类A实现[1,2]和[3], 类B实现[3] [4,5]。

2.3 依赖(倒转)倒置原则(面向接口编程)
  1. 抽象不应该依赖细节,细节应该依赖抽象
  2. 依赖(倒转)倒 置的原则是面向接口编程
  3. 设计理念: 相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。
  4. 在java中,抽象指的是接口或抽象类,细节就是具体的实现类。使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。
  5. 低层模块要尽量都有抽象方法或者接口,程序稳定性更好。
  6. 变量的声明类型尽量是抽象类或者接口,这样变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化
  7. 继承时遵循里氏替换原则
2.4 里氏替换原则(如何正确使用继承)
  1. 继承包含这样一层含义,父类中凡是实现好的方法,实际上是在制定规则,虽然不强制要求遵守(不能修改),但是如果重写了,就会对整个继承体系造成破坏。
  2. 继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他类继承,当这个类需要修改时,就要考虑到所有的子类可能出现的故障
  3. 里氏替换原则其实就是:如何正确使用继承 - > 使用继承时,尽量不重写父类的方法
  4. 如果非要继承,还要修改,可以设置一个基础类用来成为两个类共同的父类,重写这个基础类的方法(降低两个类的耦合)。
  5. 里氏替换原则告诉我们,继承实际上让两个类的耦合性增强了,在适当情况下,可以通过聚合,组合,依赖来解决问题。
2.5 开闭原则 OCP(Open Closed Principle) (对扩展开放,对修改关闭)
  1. 开闭原则(Open Closed Principle)是编程中最基础、最重要的设计原则
  2. 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)用抽象构建框架,用实现扩展细节。 其实就是 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。
  3. 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则
2.6 迪米特法则(只与直接的朋友通信)
  1. 一个对象应该对其他对象保持最少的了解
  2. 类与类关系越密切,耦合度越大
  3. 迪米特法则( Demeter Principle又叫最少知道原则,即一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的 public方法,不对外泄露任何信。
  4. 迪米特法则还有个更简单的定义:只与直接的朋友通信。
  5. 直接的朋友: 每个对象都会与其他对象由耦合关系,只要两个对象之间有耦合关系我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合等。其中,我们称出现在成员变量,方法参数,方法返回值中的类为直接的朋友,而 出现在局部变量中的类不是直接的朋友。也就是说,陌 生的类最好不要以局部变量的形式出现在类的内部。
  6. 简单来说,一个类B如果不是另一个类A的直接朋友,不要与A通信(出现在类A里)
  7. 迪米特法则的核心是降低类之间的耦合
  8. 但是注意,每个类都减少了不必要的依赖,因此迪米特法则只是要求降低类(对象)间的耦合关系,并不是要求完全没有依赖关系。
2.7 合成复用原则、
  1. 尽量使用合成/聚合的方式,而不是继承。
    • 合成(UML中的组合关系,部分和整体生命周期一致,部分不能独立于整体存在): 代码实现: 成员变量使用要引用的类,初始化默认值时,new一个对应类的实例。
    • 聚合(UML里也叫聚合,部分和整体生命周期可以不一致,部分能独立于整体存在)代码实现: 成员变量使用要引用的类,不指定默认值,使用set方法指向实例。
2.8 设计原则核心思想总结
  1. 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
  2. 针对接口编程,而不是针对实现编程。
  3. 为了交互对象之间的松耦合设计而努力。

三、参考资料

  1. 尚硅谷Java设计模式(图解+框架源码剖析)
  2. 别再找了,这就是全网最全的SpringBean的作用域管理
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值