设计模式

JAVA

# 一、设计模式

# 为什么引入设计模式

项目的业务是在不断变化迭代,引入设计模式的前提,就是在变化的需求中,找到那些稳定的部分。当代码在变化的过程中能够找到稳定的部分,才有引入设计模式的价值。

# 二、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。

使用步骤

  1. 定义一个抽象类;
  2. 定义两个方法:一个是模板方法存放相同代码部分,一个是抽象方法具体的方法交给子类实现;
  3. 子类继承抽象类,重写抽象方法。

# 9、门面模式

门面模式(外观模式 facade)

为子系统中的一组接口提供一个一致的接口。

Facade模式定义了一个高层接口,使得使用子系统一系列的接口更便捷。

案例

subway-site-device模块,提供调用各种设备的统一入口,具体设备的建立连接,由该模块来进行实现,使得调用者只需关注site-device模块即可。而后续对设备的替换变更,都于用户来说是透明不可见的,不受影响。

# 10、观察者模式

观察者模式 Onserver

定义了对象中的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者都是收到通知并更新。

优点

# 11、适配器模式

适配器模式 Adapter

将一个类的接口转换为客户希望的另一个接口。

Adapter模式使得原来由于接口不兼容而不能一起工作的那些类,可以一起工作。

有两种:Object AdaperClass Adaper

对象的Adaper模式是采用组合的形式,而类的Adaper模式是采用继承。

# 12、享元模式

运用共享技术有效的支持大量细粒度的对象。

优点

如果系统中有大量类似的对象,可以节约大量的内存和CPU资源。

解读

各种中间件的连接池,还有类中初始化定义的Map结构,当某一对象创建过一次后存储起来,下次再次调用时直接获取,不用重新创建,实现共享对象。

案例