工厂模式
简单工厂模式
概念: Simple Factory Pattern, 由一个工厂对象决定创建出哪一种产品类的实例, 不属于GOF23种设计模式。适用于工厂类创建的对象较少的场景,客户端需要传入工厂类的参数,对于创建的逻辑并不关心。
源码示例: Calendar, LoggerFactory, DateFormat
经典写法:
public ICource create(String className){
try{
if(StringUtils.isNotBlank(className)){
return (ICource)Class.forName(className).newInstance();
}
}catch(Exception e){
e.printStackTrace();
}
return null;
}
工厂方法模式
概念: Factory Method Pattern, 定义一个创建对象的接口, 让实现这个接口的类来决定实例化哪个类, 工厂方法让类的实例化推迟到子类中进行。主要解决的是产品扩展的问题。
源码示例: ILogggerFactory, Logger
抽象工厂模式
概念: 创建一系列相关或相互依赖对象的接口,无须指定它们具体的类。主要理解产品等级结构和产品族两个概念。产品族增加了系统的抽象性和理解难度。
单例模式
概念: Singleton Pattern, 是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。
源码示例: ServletContext, ServletContextConfig, ApplicationContext
饿汉式
类加载时立即初始化创建单例对象,绝对线程安全,不存在访问安全问题。
优点在于保证绝对线程安全,执行效率高。缺点在于所有对象类加载的时候就实例化, 浪费内存空间。所以饿汉式适用于单例对象较少的情况。
经典写法:
public static Hungry{
private static final Hungry hungry = new Hungry();
private Hungry(){}
public static Hungry getInstance(){
return hungry;
}
}
懒汉式
单例对象在要被使用时才会初始化。
经典写法:
public class Lazy{
private Lazy(){}
private volatile static Lazy lazy = null;
public static Lazy getInstance(){
if(null == lazy){
synchronized(Lazy.class){
if(null == lazy){
lazy = new Lazy();
}
}
}
return lazy;
}
}
这是双重检验锁(DCL)。之所以要加volatile,是为了防止指令重排序。在lazy = new Lazy();
代码中,分成分配内存给对象; 初始化对象; 设置lazy指向分配的内存地址。而后两个step可能会重排序,所以需要使用volatile禁止重排序。
静态内部类
在类初始化时进行对象初始化, 这种方法兼顾了饿汉式的内存浪费和懒汉式同步的性能问题。
public class LazyInner{
private LazyInner(){}
public static final LazyInner getInstance(){
return LazyHolder.LAZY;
}
private static class LazyHolder{
private static final LazyInner LAZY = new LazyInner();
}
}
注册式单例
将每个实例都注册到某个容器中,使用唯一标识获取单例。主要有两种: 一种是枚举式单例模式, 一种是容器式单例模式。
枚举式单例模式,就是利用枚举
容器式单例模式案例:
public class Container{
private Container(){}
private static Map<String, Object> ioc = new ConcurrentHashMap<String,Object>();
public static Object getBean(String className){
synchronized (ioc){
if(!ioc.containsKey(className)){
Object obj = null;
try{
obj = Class.forName(className).newInstance();
ioc.put(className, obj);
} catch (Exception e){
e.printStackTrace();
}
return obj;
}
return ioc.get(className);
}
}
}
ThreadLocal线程单例
ThreadLocal将所有的对象都放在ThreadLocalMap中, 为每个线程都提供一个对象,以空间换时间实现线程隔离。
两种破坏单例的情况: 反射破坏&序列化破坏
反射破坏通过构造方法中抛异常可以防止, 序列化破坏是要增加readResolve方法可以防止
原型模式
概念: Prototype Pattern, 原型实例指定创建对象的种类, 通过拷贝这些原型创建新的对象。主要包含三个角色: 客户, 抽象原型, 具体原型。
主要适用于
- 类初始化消耗资源较多
- new产生的一个对象需要非常繁琐的过程
- 构造函数比较复杂
- 循环体中生产大量对象
一般用序列化实现深克隆。
建造者模式
概念: Builder Pattern, 将一个复杂对象的构建过程和它的表示分离,使同样的构建过程可以创建不同的表示,属于创建型模式。主要包含产品,建造者抽象,建造者, 调用者四个角色。
适用于创建对象需要很多步骤, 但是步骤的顺序不一定固定。
建造者模式可以用来校验必填项,设置各属性的依赖关系,设置不可变对象。