# 一、设计模式
# 为什么引入设计模式
项目的业务是在不断变化迭代,引入设计模式的前提,就是在变化的需求中,找到那些稳定的部分。当代码在变化的过程中能够找到稳定的部分,才有引入设计模式的价值。
# 二、23种设计模式
# 1、单例设计模式
保证对象唯一性,不允许使用new
来创建该类对象。在该类中创建一个实例,对外提供一个方法进行获取该对象。
单例分类
饿汉式单例设计模式
//饿汉式(静态变量) class Singleton { //私有化构造器,外部不能new private Singleton() { } //本类内部创建对象实例 private final static Singleton instance = new Singleton(); //提供一个公有的静态方法,返回实例对象 public static Singleton getInstance() { return instance; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14懒汉式(延时加载)单例设计模式
//懒汉式(线程安全) class Singleton { private Singleton() { } private static Singleton instance; public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14懒汉式改进版——双重锁(双重判断加同步锁)
//懒汉式(双重检查) class Singleton { private Singleton() { } // volatile:一有修改就更新到主存里边去 private static volatile Singleton instance; public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 2、代理模式
为了保证行为的一致性,代理类和委托类通常会实现相同的接口。所以在调用者来看,两者是一样的。
通过代理类能有效控制对委托类对象的直接访问,可以很好地隐藏和保护委托类对象。
# 3、建造者模式
Builder模式,将一个复杂对象的创建,与它的表示进行分离,使得同样的构建过程,可以产生不同的表示。
场景:
需要构建的对象具有复杂的内部结构;
内部属性本身相互依赖;
Builder模式的变种,将对象的成员属性设置为final,不提供setter方法,而是在对象内部定义内部静态类Builder,通过构建Builder来进行对成员属性的赋值操作。
# 4、工厂方法模式
工厂方法模式(Factory Method)
定义一个用于创建对象的接口,让子类去决定实例化哪一个类。该模式将类的实例化延时到子类去执行。
# 5、责任链模式
为请求创建了一个接受者对象的链。是一种线性的数据结构。一个请求的处理需要多个对象中的一个或多个协助处理。可以控制先后顺序。
# 6、装饰器模式
装饰器模式 Decorator
在不改变现在方法的基础上,继承后扩展自己的方法。扩展一个类的功能,或者给一个类添加附加职责。
解读:
原本有一个类写了一个方法,但不满足我现有需求,我需要在其基础之上进行扩展。
1 那么就使用该模式,重新定义一个抽象类继承该类;
2 定义实现类,重写父类方法,增加自定义需求。
案例:
# 7、策略模式
策略模式 Strategy
定义了算法簇,分别封装起来,让他们之间可以相互替换。
案例:
在进行设备统计时,每一种设备需要统计的数据各不相同,即统计算法不一样。所以抽离一个共性统计方法,定义设备类型,具体统计算法由各子类实现。那么在获取设备统计controller接口提供统一入口,根据设备类型枚举项动态获取是统计哪一类设备数据。
# 8、模板方法模式
模板方法就是当系统中出现同一个功能多处在开发,而该功能中大部分代码是一样的,只有其中部分可能不同的时候使用的一种抽象方法。
定义一个操作的算法骨架,而将一些步骤延迟到子类中。子类实现后再不改变原有算法的结构,即可重新定义某些特定步骤。
解读:
对于那些模板定式结构的方法,抽象一个父类规范方法算法骨架,核心逻辑代码交由子类去实现。
案例:
netty服务端启动类,子类实现管道中添加自定义handler。
使用步骤:
- 定义一个抽象类;
- 定义两个方法:一个是模板方法存放相同代码部分,一个是抽象方法具体的方法交给子类实现;
- 子类继承抽象类,重写抽象方法。
# 9、门面模式
门面模式(外观模式 facade)
为子系统中的一组接口提供一个一致的接口。
Facade模式定义了一个高层接口,使得使用子系统一系列的接口更便捷。
案例:
subway-site-device模块,提供调用各种设备的统一入口,具体设备的建立连接,由该模块来进行实现,使得调用者只需关注site-device模块即可。而后续对设备的替换变更,都于用户来说是透明不可见的,不受影响。
# 10、观察者模式
观察者模式 Onserver
定义了对象中的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者都是收到通知并更新。
优点:
# 11、适配器模式
适配器模式 Adapter
将一个类的接口转换为客户希望的另一个接口。
Adapter模式使得原来由于接口不兼容而不能一起工作的那些类,可以一起工作。
有两种:Object Adaper
,Class Adaper
对象的Adaper模式是采用组合的形式,而类的Adaper模式是采用继承。
# 12、享元模式
运用共享技术有效的支持大量细粒度的对象。
优点:
如果系统中有大量类似的对象,可以节约大量的内存和CPU资源。
解读:
各种中间件的连接池,还有类中初始化定义的Map结构,当某一对象创建过一次后存储起来,下次再次调用时直接获取,不用重新创建,实现共享对象。
案例: