# 单例模式

  1. 懒汉(线程不安全,懒加载):如果没有实例就创建并返回,会有线程安全问题,简单加synchronized解决,但效率不高,升级版本是DCL
  2. 懒汉的升级DCL(线程安全,懒加载):加两个if是因为可能会有多个线程一起进入同步块外的if,如果在同步块内不进行二次检验的话就会生成多个实例了;instance = new Singleton()这句会有重排序的问题,用volidate解决
  3. 饿汉(线程安全,非懒加载):利用类加载器保证线程安全,但不是懒加载
  4. 饿汉升级静态内部类(线程安全,懒加载):在饿汉的基础上使用静态内部类解决非懒加载问题
  5. 枚举(线程安全,非懒加载):写法最简单,防止反序列化,但不是懒加载
    一般情况下直接使用饿汉式就好了,如果明确要求要懒加载会倾向于使用静态内部类,如果涉及到反序列化创建对象时会试着使用枚举的方式来实现单例。

http://wuchong.me/blog/2014/08/28/how-to-correctly-write-singleton-pattern

# 装饰器模式

在保持原有功能接口不变的基础上动态扩展功能的模式。
Java IO包中就使用了该模式,InputStream有太多的实现类如FileInputStream,如果要在每个实现类上加上几种功能如缓冲区读写功能Buffered,则会导致出现ileInputStreamBuffered, StringInputStreamBuffered等等,如果还要加个按行读写的功能,类会更多,代码重复度也太高,你说改原来的接口也行啊,但是这样就是改变接口的内容了,现在我想做到不更改以前的功能,动态地增强原有接口。
所以使用FilterInputStream这个抽象装饰器来装饰InputStream,使得我们可以用BufferedInputStream来包装FileInputStream得到特定增强版InputStream,且增加装饰器种类也会更加灵活。

缺点:
会引入很多小类,从而增加使用复杂度,多层装饰的时候很容易导致不知道如何使用

# 策略模式

一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。

比如利用策略模式优化过多 if else 代码,将这些if else算法封装成一个一个的类,任意地替换

整体思路如下:

  1. 定义一个 InnerCommand 接口,其中有一个 process 函数交给具体的业务实现。
  2. 根据自己的业务,会有多个类实现 InnerCommand 接口;这些实现类都会注册到 Spring Bean 容器中供之后使用。
  3. 通过客户端输入命令,从 Spring Bean 容器中获取一个 InnerCommand 实例。
  4. 执行最终的 process 函数。

https://juejin.im/post/5c5172d15188256a2334a15d

缺点:

  1. 策略类会增多
  2. 所有策略类都需要对外暴露。

# 观察者模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式使用三个类 Subject、Observer 和 Client。Subject 对象带有绑定观察者到 Client 对象和从 Client 对象解绑观察者的方法。我们创建 Subject 类、Observer 抽象类和扩展了抽象类 Observer 的实体类。

缺点:

  1. 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间
  2. 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃
  3. 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化