一、设计模式的形与意
1、形(实现):是指这种设计模式的一种通用形式,可能存在变体
2、意(抽象):是指这种设计模式的含义,用什么方式来解决什么问题等
3、形意结合:深知其意,以意驱动其形,希望能通过意记作其形。用形来实现其意
一、简单工厂模式:(简单工具类)
1、类拥有一个静态方法作为组件的工厂方法
2、通用形式:
1、静态工厂方法建议返回类型使用:抽象类型或接口(父类)
2、静态工厂方法建议指定参数,方法实现根据参数if-else创建对应的组件(子类)
二、工厂方法模式(管理对象的创建)
1、它是静态工厂模式的扩展,它将静态工厂类中的工厂方法实现中的if-else抽取成每个产品的工厂类。
1、针对目标:某一类特定产品
3、通用形式:
1、定义工厂接口
2、定义工厂实现类,专注某一产品类对象的创建(工厂方法)
3、工厂方法返回类型为:产品的抽象类或接口
4、特点:典型的解耦框架(产品框架与客户端框架),高层模块(客户端)只需知道产品的抽象类或接口,无需关心产品的实现类,产品的创建类。满足迪米特,依赖倒置、里氏替换原则
三、抽象工厂模式(产品族的工厂)
1、它是在工厂方法模式下,提供了针对某产品的产品族(同属于某一根产品,但类别不同,等级相当,且之间有着相互关联或配合的产品集合)的一组工厂方法,为一类产品的产品族提供了一个统一的创建框架。
针对目标:某类产品的产品族
2、产品族是指在同一主题或设计理念下,相互关联或配套的一系列产品集合
3、通用形式:
1、归纳产品到对应的产品族
2、构建产品族框架
1、定义抽象产品
2、定义产品的多个实现类(产品族)
3、根据产品族构建对应的工厂框架
1、定义抽象工厂,定义产品族中各产品的工厂方法
2、定义工厂的多个实现类(产品族的工厂)
4、特点:它是从逻辑分类维度上将一组相关的产品强行绑定到一起
四、单例模式(全局唯一实例)
1、确保一个类在任何情况下只有一个实例,并提供全局访问点供外部访问
2、目标:保证在一个JVM中只存在单一实例。
3、应用场景:
1、需要频繁创建的一些类,使用单例模式可降低系统的内存压力,减少GC
2、某些类创建实例时占用资源较多,或实例化耗时较长,且经常使用。
3、对于一些控制硬件级别的操作,或从系统上来讲应当是单一控制逻辑的操作,若有多个实例则会系统乱套
4、通用形式
1、定义单例类,构造方法全部定义为private
2、对外提供获取单例对象的方法:static Instance getInstance()
5、分类:
1、饿汉式:
1、该类加载时立即初始化,并创建单例对象,线程安全(因为在线程还没出现之前单例就存在了)
2、写法1:
1、定义成员变量:private static final Singletion instane = new Singleton()
2、getInstance方法直接返回instance
3、写法2:
1、定义成员变量:private static final Singletion instane
2、定义静态代码块,在代码块中创建并注入instance
3、getInstance方法直接返回instance
4、写法3:将单例定义为枚举
4、场景:适用于单例对象较少的情况
2、懒汉式:
1、单例对象在被使用时才会初始化
2、写法1:
1、定义私有静态内部类,内部类中持有单例的成员变量(在内部类加载时初始化单例实例)
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton()
}
2、getInstance方法中,调用内部类的INSTANCE(此时会触发内部类的类加载机制)
3、写法2:双重检查 + 锁 + volatile
4、线程的单例:线程内唯一单例,但在全局(存在多线程下)下有多个
1、定义私有静态内部类,
2、内部类中定义:private static final ThreadLocal<Object> INSTANCE = ThreadLocal.withInitial(Object::new);
3、外部单例类访问方法:
public static ObjectgetInstance() {
return InnerHolder.INSTANCE.get();
}
6、存在问题:
1、通过反射调用单例类的构造方法,从而破坏单例模式,解决方法:在私有构造方法中判断INSTANCE为null(为null则抛异常)
2、单例类实现了Serializable接口,当使用反序列构建单例时会生成新对象从而破坏单例模式,解决方法:单例类中增加readResolve()方法,不能完全解决依然会创建新对象,只是返回给调用方的是单例
private Object readResolve() {
return INSTANCE;
}
五、原型模式:(当前对象(有状态)的快照)
1、定义:以系统中已存在的一个对象为原型,基于内存二进制流进行复制而非new关键字(其过程不调用对象构造方法)创建对象的模式
2、适用场景:
1、系统已存在的对象,对象的创建成本较大(初始化耗时长,占用CPU太多,占用网络资源太多)
2、自动存档、快照,异步执行等场景
3、目标:需要一份现有的,已配置好的当前对象(可能经历过多重工序,具有一定状态的(属性)对象)的新对象
1、新对象在内容与当前对象完全相同
2、新对象与当前对象不是同一对象
4、通用形式:
1、定义原型接口(可省略),定义clone()接口
2、定义原型的实现类,实现clone方法,
1、实现方式1(浅拷贝):如果委托给父类Object的clone(),需要让原型实现Cloneable接口
在内存中分配一块新内存,然后将原型对象以二级制流的方式复制到新内存中,该方式性能高效
2、实现方式2(深拷贝):如果是通过序列化方式(将this写入字节数组流,再从流读取成新对象),需要让原型实现Serializable接口
该方式能保存或恢复对象的状态数据
六、建造模式(简化属性装配)
1、定义:它在工厂方法模式的基础上,增加了对产品的模块化和定制化的封装。
1、模块化:即产品的属性,可注入不同的值(基本数据类型和引用)或不注入
2、定制化:将该产品的所有属性的值(具体数据),先创建一个具体产品作为基底,然后此基础上,按定制化需求为该产品注入不同的属性(注入或不注入,或注入a1或注入a2)
2、核心目标:建造者的重点在注入属性上
3、通用形式:
1、定义属性
2、定义内部类 public static class Builder
1、定义产品框架
1、定义产品接口
2、定义产品的实现类
2、定义建造者框架
1、定义Builder接口
1、定义产品的多个注入属性方法(buildPartA()、buildPartB()…)
2、定义获取产品接口,如果没有导演类,就应该换成是建造者方法(build())
2、定义Builder的实现类
1、需要先创建产品实例
2、注入属性委托给产品
3、定义导演类(可省略)
1、注入并持有Builder
2、建造方法:
1、创建产品
2、安排属性的注入
3、返回产品
4、适用场景:
1、简单无参创建产品实例,同时可根据自身需求为产品的注入属性
2、链式编程,让调用方的创建产品代码更简洁
5、鉴定:
1、有返回产品的建造方法build()
2、有设置产品属性的注入方法