创建型
简单工厂
-
模式动机
简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。
-
类图
-
优缺点
- 优点:结构简单
- 缺点:不便于扩展
-
案例
jdk中简单工厂:- java.util.Calendar.getInstance();
- java.sql.DriverManager.getConnection()
框架中简单工厂使用:
- logback#loggerFactory.getLogger();
工厂方法(产品等级)
-
模式动机
工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。工厂方法模式是一种类创建型模式。
-
类图
-
优缺点
优点:- 克服了简单工厂违背开放-封闭原则的缺点,又保留了封装对象创建过程的优点,降低客户端和工厂的耦合性
缺点:
- 每增加一个产品,相应的也要增加一个子工厂,加大了额外的开发量
-
案例
jdk中的使用:- Collection中的iterator方法
- java.net.URLStreamHandlerFactory
- java.util.EnumSet
- java.lang.Proxy#newProxyInstance()
- java.lang.Object#toString()
- java.lang.Class#newInstance()
- java.lang.reflect.Array#newInstance()
- java.lang.reflect.Constructor#newInstance()
- java.lang.Boolean#valueOf(String)
- java.lang.Class#forName()
抽象工厂(产品族)
- 模式动机
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。
- 类图
- 优缺点
抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式。 - 案例
- UIManager(swing外观)
- java.sql
单例模式
-
模式动机
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式是一种对象创建型模式。
-
实现方式
-
懒汉式
public class LazySingleton { private static LazySingleton lazySingleton = null; private LazySingleton(){ if(lazySingleton != null){ throw new RuntimeException("单例构造器禁止反射调用"); } } public synchronized static LazySingleton getInstance(){ if(lazySingleton == null){ lazySingleton = new LazySingleton(); } return lazySingleton; } }
-
饿汉式
public class HungrySingleton implements Serializable{ private final static HungrySingleton hungrySingleton; static{ hungrySingleton = new HungrySingleton(); } private HungrySingleton(){ //私有构造器 if(hungrySingleton != null){ //防止反射调用 throw new RuntimeException("单例构造器禁止反射调用"); } } public static HungrySingleton getInstance(){ return hungrySingleton; } private Object readResolve(){ //防止序列化破坏单例 return hungrySingleton; } }
-
双重校验锁
public class Singleton { private volatile static Singleton uniqueInstance; private Singleton() { } public static Singleton getUniqueInstance() { if (uniqueInstance == null) { synchronized (Singleton.class) { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } } } return uniqueInstance; } }
-
静态内部类
public class Singleton { private Singleton() { } private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getUniqueInstance() { return SingletonHolder.INSTANCE; } }
-
枚举(最佳实践)
public enum EnumInstance { INSTANCE { protected void printTest() { System.out.println("singleton by enum"); } }; protected abstract void printTest(); private Object data; public Object getData() { return data; } public void setData(Object data) { this.data = data; } public static EnumInstance getInstance() { return INSTANCE; } }
-
容器单例
public class ContainerSingleton { private ContainerSingleton() { } private static Map<String, Object> singletonMap = new HashMap<String, Object>(); public static void putInstance(String key, Object instance) { if (!isBlank(key) && instance != null) { if (!singletonMap.containsKey(key)) { singletonMap.put(key, instance); } } } private static boolean isBlank(String cs) { int strLen; if (cs != null && (strLen = cs.length()) != 0) { for (int i = 0; i < strLen; ++i) { if (!Character.isWhitespace(cs.charAt(i))) { return false; } } return true; } else { return true; } } public static Object getInstance(String key) { return singletonMap.get(key); } }
-
ThreadLocal单例
public class ThreadLocalInstance { private static final ThreadLocal<ThreadLocalInstance> threadLocalInstanceThreadLocal = ThreadLocal.withInitial(ThreadLocalInstance::new); private ThreadLocalInstance(){ } public static ThreadLocalInstance getInstance(){ return threadLocalInstanceThreadLocal.get(); } }
-
-
优缺点
优点:- 在内存中只有一个对象,节省内存空间。
- 避免频繁的创建销毁对象,可以提高性能。
- 避免对共享资源的多重占用。
- 可以全局访问。
缺点: - 多线程环境中需要注意线程安全问题
-
案例
JDK中的使用:- java.lang.Runtime#getRuntime()
- java.awt.Desktop#getDesktop()
- java.lang.System#getSecurityManager()
框架中的使用:
- Spring#FactoryBean
- myBatis#ErrorContext
原型模式
-
模式动机
使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式是一种对象创建型模式。
-
类图
-
优缺点
优点:- 当创建对象的实例较为复杂的时候,使用原型模式可以简化对象的创建过程,通过复制一个已有的实例可以提高实例的创建效率。
- 扩展性好,由于原型模式提供了抽象原型类,在客户端针对抽象原型类进行编程,而将具体原型类写到配置文件中,增减或减少产品对原有系统都没有影响。
- 原型模式提供了简化的创建结构,工厂方法模式常常需要有一个与产品类等级结构相同的工厂等级结构,而原型模式不需要这样,圆形模式中产品的复制是通过封装在类中的克隆方法实现的,无需专门的工厂类来创建产品。
- 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
缺点:
- 需要为每一个类配置一个克隆方法,而且该克隆方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反了开闭原则。
- 在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重签到引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。
-
案例
- java.lang.Object#clone()
建造者模式
- 模式动机
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一种对象创建型模式。
-
类图
-
优缺点
优点- 将一个对象分解为各个组件
- 将对象组件的构造封装起来
- 可以控制整个对象的生成过程
缺点
- 对不同类型的对象需要实现不同的具体构造器的类,这可能大大增加类的数量
-
案例
- java.lang.StringBuilder
- java.nio.ByteBuffer
- java.lang.StringBuffer
- java.lang.Appendable
- Guava#CacheBuider/ImmutibleSet.Builder
- Spring#BeanDefinitionBuilder
- MyBatis#SqlSessionFactoryBuilder/XmlConfigBuilder