设计模式

设计模式其实就是对面向对象特性的应用。封装、继承和多态,其中多态是实现各种设计模式的基础。

通过接口或者抽象类编程,实现了动态扩展,不同的子类对象都可以通过接口对象调用,那么如果想添加新的具体实现,可以通过通过配置的方式实现,而不用修改代码。

并且可以实现依赖反转,并不需要在使用类中创建依赖类对象,可以采用接口注入的放入传入依赖的类对象。

创建型

单例模式

spring中bean对象默认就是单例模式的,当然也可以修改为多例模式

工厂模式

工厂模式是用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。

spring中的BeanFactory中的getbean就是

构造器模式

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

如果存在下面情况中的任意一种,我们就要考虑使用建造者模式了。

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

形式就是使用Builder子类完成创建对象

原型模式

比如spring中bean对象的scope为prototype时。

如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式来创建新对象,以达到节省创建时间的目的。这种基于原型来创建对象的方式就叫作原型设计模式(Prototype Design Pattern),简称原型模式。

那何为“对象的创建成本比较大”?

实际上,创建对象包含的申请内存、给成员变量赋值这一过程,本身并不会花费太多时间,或者说对于大部分业务系统来说,这点时间完全是可以忽略的。应用一个复杂的模式,只得到一点点的性能提升,这就是所谓的过度设计,得不偿失。

但是,如果对象中的数据需要经过复杂的计算才能得到(比如排序、计算哈希值),或者需要从 RPC、网络、数据库、文件系统等非常慢速的 IO 中读取,这种情况下,我们就可以利用原型模式,从其他已有对象中直接拷贝得到,而不用每次在创建新对象的时候,都重复执行这些耗时的操作。

深拷贝和浅拷贝

Java对象的clone方法默认只会拷贝对象的引用,这时新旧对象其实还是指向的同一个对象,就会出现被意外修改的问题。

这个时候就需要进行深拷贝了,深拷贝主要有两种方法:

递归拷贝

递归拷贝对象、对象的引用对象以及引用对象的引用对象……直到要拷贝的对象只包含基本数据类型数据,没有引用对象为止。

序列化

先将对象序列化,然后再反序列化成新的对象。具体的示例代码如下所示:

public Object deepCopy(Object object) {
  ByteArrayOutputStream bo = new ByteArrayOutputStream();
  ObjectOutputStream oo = new ObjectOutputStream(bo);
  oo.writeObject(object);
  
  ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
  ObjectInputStream oi = new ObjectInputStream(bi);
  
  return oi.readObject();
}

刚刚的两种实现方法,不管采用哪种,深拷贝都要比浅拷贝耗时、耗内存空间。针对我们这个应用场景,有没有更快、更省内存的实现方式呢?

采用Copy-On-Write的思想,刚开始还是还是浅拷贝,只有需要修改对象时,才重新创建另一个新的对象

结构型

装饰器模式

作用就是增强类功能,比如spring中的注解

InputStream及其相关的具体实现类 

代理模式

代理需要有代理对象和目标对象。实现的方式有静态代理和动态代理两种。spring的aop就是采用动态代理的方式实现的。

桥接模式

适配器模式

adapter,比如虚拟文件接口,各种抽象接口,mybatis中dao层的接口实现。

组合模式

通过多类组合成新的类,功能更强大。对应的是多继承。

门面模式

Facade模式。比如Tomcat中的很多容器类,还有JUnit类都是门面类。

使用场景:当我们希望封装或隐藏原系统;当我们使用原系统的功能并希望增加一些新的功能;编写新类的成本远小于所有人学会使用或者未来维护原系统所需的成本;
缺点:违反了开闭原则。如有扩展,只能直接修改代理对象。

行为型

观察者模式

比如spring和Tomcat中的各种事件监听

模板模式

jdbctemplate

策略模式

职责链模式

Tomcat和jetty中将请求交给一个个子容器来处理。

迭代器模式

Java中的iterator接口

状态模式

posted on 2020-05-08 18:45  simple_孙  阅读(107)  评论(0编辑  收藏  举报

导航