icql

创建型设计模式概述

主要解决对象的创建问题



单例模式

定义:一个类只允许创建一个实例 使用场景:处理资源访问冲突;数据在系统种只应该保存一份(如配置信息) 实现方式:主要考虑以下3个方面:构造函数private,创建对象线程安全,是否延迟加载

存在的问题:

单例对OOP特性支持不友好:封装/继承/多态/抽象 单例会隐藏类之间的依赖关系:类似于工具类一样使用时属于硬编码,不便查找 单例对代码的扩展性不友好 单例对代码的可测试性不友好:由于类似硬编码,不方便mock 单例不支持有参数的构造函数

单例的替代方式:工厂模式,ioc容器

单例的作用范围:

进程内唯一(大多数情况) 线程内唯一(用类似ThreadLocal的Map即可实现) 多进程内唯一(分布式),用一个集中式的共享区域存储,如db数据库等

1)饥饿式

/**
 * 单例:饥饿模式——类加载时就创建对象
 * 过早占用内存,存在性能问题?
 * 若初始化耗时,应该在应用启动时就初始化好,避免使用时再创建出现性能问题
 * 占用内存多?按照fail-fast设计原则(有问题及早暴漏),启动时就能检查内存是否够用
 */
public final class EagerSingleton {
    /**
     * 类加载的时候执行clinit()时将创建对象,线程安全
     */
    private static final EagerSingleton INSTANCE = new EagerSingleton();

    private EagerSingleton() {
    }

    public static EagerSingleton getInstance() {
        return INSTANCE;
    }
}

2)懒汉式

/**
 * 单例:懒汉模式——延迟加载
 * 同步范围过大(锁对象为类Class对象),性能不佳
 */
public final class LazySingleton {

    private static LazySingleton INSTANCE;

    private LazySingleton() {
    }

    public synchronized static LazySingleton getInstance() {
        if (INSTANCE != null) {
            INSTANCE = new LazySingleton();
        }
        return INSTANCE;
    }
}

3)双重检测

/**
 * 单例:双重检测
 *
 * 初始化对象的3个步骤:
 * 1)分配内存空间
 * 2)初始化对象
 * 3)将内存空间的地址赋值给对应的引用
 * 由于虚拟机有指令重排优化机制,上述步骤可能会变为 1-3-2,所以需要 volatile 关键字来保证禁止重排指令,
 * 如果以1-3-2顺序执行,线程A运行到第2次检查通过后正在初始化对象,初始化对象需要一定时间,这时步骤已完成1和3,
 * 线程B运行到第1次检查发现不为null,则直接返回,实际上 线程A还没有完成初始化对象的步骤2,造成了jvm异常
 */
public final class DoubleCheckedSingleton {

    private volatile static DoubleCheckedSingleton INSTANCE;

    private DoubleCheckedSingleton() {
    }

    public static DoubleCheckedSingleton getInstance() {
        //第1次检查
        if (INSTANCE == null) {
            synchronized (DoubleCheckedSingleton.class) {
                //第2次检查
                if (INSTANCE == null) {
                    INSTANCE = new DoubleCheckedSingleton();
                }
            }
        }
        return INSTANCE;
    }
}

4)静态内部类

/**
 * 单例:内部类-懒加载
 */
public final class InnerClassSingleton {
    private InnerClassSingleton() {
    }

    private static class SingletonHolder {
        public static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
    }

    public static InnerClassSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

5)枚举

/**
 * 单例:枚举
 */
public enum EnumSingleton {
    INSTANCE
}



多例模式

特殊的单例,一个类允许有固定的多个实例,区别于工厂模式,多例是同一个类型的多个实例,而工厂模式是多个不同子类的实例

实现方式:枚举 或 使用map结构

/**
 * 多例:枚举
 */
public enum EnumMultiton {
    INSTANCE1,
    INSTANCE2,
    INSTANCE3
}

/**
 * 多例:双重检测
 */
public final class DoubleCheckedMultiton {

    private static final Map<String, DoubleCheckedMultiton> INSTANCE_BY_NAME = new HashMap<>();

    private DoubleCheckedMultiton() {
    }

    public static DoubleCheckedMultiton getInstance(String name) {
        DoubleCheckedMultiton INSTANCE = INSTANCE_BY_NAME.get(name);
        //第1次检查
        if (INSTANCE == null) {
            synchronized (DoubleCheckedMultiton.class) {
                //第2次检查
                if (INSTANCE == null) {
                    INSTANCE = new DoubleCheckedMultiton();
                    INSTANCE_BY_NAME.put(name, INSTANCE);
                }
            }
        }
        return INSTANCE;
    }
}



工厂模式

用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象

1)简单工厂

工厂类直接创建对象,static方法,最简单

/**
 * 简单工厂模式
 */
public class Factory {

    private static final Map<String, IObject> OBJECT_BY_TYPE = new HashMap<>();

    static {
        OBJECT_BY_TYPE.put("A", new ObjectA());
        OBJECT_BY_TYPE.put("B", new ObjectB());
        OBJECT_BY_TYPE.put("C", new ObjectC());
    }

    public static IObject createObject(String type) {
        if (type == null || type.isEmpty()) {
            return null;
        }
        return OBJECT_BY_TYPE.get(type.toUpperCase());
    }
}

public interface IObject {
}

public class ObjectA implements IObject {
}

public class ObjectB implements IObject {
}

public class ObjectC implements IObject {
}

2)工厂方法

将创建对象的行为下沉到各个类型自己的工厂类中,这些类型工厂类实现一个工厂接口,和工厂接口一起再使用一个简单工厂模式对外暴漏

/**
 * 工厂方法模式
 */
public class Factory {

    private static final Map<String, ObjectFactory> FACTORY_BY_TYPE = new HashMap<>();

    static {
        FACTORY_BY_TYPE.put("A", new ObjectAFactory());
        FACTORY_BY_TYPE.put("B", new ObjectBFactory());
        FACTORY_BY_TYPE.put("C", new ObjectCFactory());
    }

    public static ObjectFactory createObject(String type) {
        if (type == null || type.isEmpty()) {
            return null;
        }
        return FACTORY_BY_TYPE.get(type.toUpperCase());
    }
}

public interface IObject {
}

public interface ObjectFactory {
    IObject createObject(String type);
}

public class ObjectAFactory implements ObjectFactory {
    @Override
    public IObject createObject(String type) {
        //复杂的创建逻辑
        return new ObjectA();
    }
}

public class ObjectBFactory implements ObjectFactory {
    @Override
    public IObject createObject(String type) {
        //复杂的创建逻辑
        return new ObjectB();
    }
}

public class ObjectCFactory implements ObjectFactory {
    @Override
    public IObject createObject(String type) {
        //复杂的创建逻辑
        return new ObjectC();
    }
}

public class ObjectA implements IObject {
}

public class ObjectB implements IObject {
}

public class ObjectC implements IObject {
}

3)抽象工厂

不常用,相当于原来的实例可以通过两个维度去划分,在工厂方法的基础上,每个维度创建实例都在工厂方法中有对应的方法

/**
 * 抽象工厂模式
 */
public class Factory {

    private static final Map<String, ObjectFactory> FACTORY_BY_TYPE = new HashMap<>();

    static {
        FACTORY_BY_TYPE.put("A", new ObjectAFactory());
        FACTORY_BY_TYPE.put("B", new ObjectBFactory());
        FACTORY_BY_TYPE.put("C", new ObjectCFactory());
    }

    public static ObjectFactory createObject(String type) {
        if (type == null || type.isEmpty()) {
            return null;
        }
        return FACTORY_BY_TYPE.get(type.toUpperCase());
    }
}

public interface IObject {
}

public interface IObjectA extends IObject {
}

public interface IObjectB extends IObject {
}

public interface IObjectC extends IObject {
}

public interface ObjectFactory {

    IObject createObject1(String type);

    IObject createObject2(String type);
}

public class ObjectA1 implements IObjectA {
}

public class ObjectA2 implements IObjectA {
}

public class ObjectB1 implements IObjectB {
}

public class ObjectB2 implements IObjectB {
}

public class ObjectC1 implements IObjectC {
}

public class ObjectC2 implements IObjectC {
}

public class ObjectAFactory implements ObjectFactory {
    @Override
    public IObject createObject1(String type) {
        //复杂的创建逻辑
        return new ObjectA1();
    }

    @Override
    public IObject createObject2(String type) {
        return new ObjectA2();
    }
}

public class ObjectBFactory implements ObjectFactory {

    @Override
    public IObject createObject1(String type) {
        //复杂的创建逻辑
        return new ObjectB1();
    }

    @Override
    public IObject createObject2(String type) {
        //复杂的创建逻辑
        return new ObjectB2();
    }
}

public class ObjectCFactory implements ObjectFactory {

    @Override
    public IObject createObject1(String type) {
        //复杂的创建逻辑
        return new ObjectC1();
    }

    @Override
    public IObject createObject2(String type) {
        //复杂的创建逻辑
        return new ObjectC2();
    }
}



建造者模式

用来创建一种类型的复杂对象,通过设置不同的可选参数,”定制化”地创建不同的对象 对象一旦创建就不允许修改

/**
 * 建造者模式
 */
public class ObjectPool {

    private int fieldA;

    private String fieldB;

    private ObjectPool(Builder builder) {
        this.fieldA = builder.fieldA;
        this.fieldB = builder.fieldB;
    }

    public static class Builder {

        private int fieldA;

        private String fieldB;

        public ObjectPool build() {
            //创建ObjectPool逻辑处理
            if (fieldA < 0) {
                throw new IllegalArgumentException("...");
            }
            if (fieldB == null || fieldB.isEmpty()) {
                throw new IllegalArgumentException("...");
            }
            return new ObjectPool(this);
        }

        public Builder setFieldA(int fieldA) {
            if (fieldA < 0) {
                throw new IllegalArgumentException("...");
            }
            this.fieldA = fieldA;
            return this;
        }

        public Builder setFieldB(String fieldB) {
            if (fieldB == null || fieldB.isEmpty()) {
                throw new IllegalArgumentException("...");
            }
            this.fieldB = fieldB;
            return this;
        }
    }
}



原型模式

对象的创建成本较大,直接根据已有对象复制一个新的对象的方式 深拷贝(Deep Copy)和浅拷贝(Shallow Copy)

/**
 * 原型模式
 */
public class ProtoType {
    /**
     * 深拷贝,浅拷贝
     * 原型模式使用深拷贝,一般使用序列化相对简单,jdk原生序列化,json序列化,kryo序列化。。。
     */
}