一、单例模式
一个类只需要存在一个实例
/** * Created by Administrator on 2016/11/23. * 饿汉模式, 类加载时便创建单例, 类加载时稍慢, 运行时获取单例更快, 线程安全 */ public class SingletonHungry { private SingletonHungry() { } private static SingletonHungry instance = new SingletonHungry(); public static SingletonHungry getInstance() { return instance; } }
/** * Created by Administrator on 2016/11/23. * 懒汉模式, 第一次使用时创建单例, 类加载时比较快, 运行时获取单例稍慢, 线程不安全 */ public class SingletonLazy { private static SingletonLazy instance; private SingletonLazy() { } public static SingletonLazy getInstance() { if(instance == null) instance = new SingletonLazy(); return instance; } }
二、工厂模式
利用工厂方法代替new来实例化对象,适用于需要创建一组对象、不能预见需要哪个类的实例以及加强扩展性与解耦的场景
定义一个接口用来创建对象,让其子类决定哪些类将被实例化,即把实例化的工作推迟到子类
首先定义一个接口, 被实例化的类均实现了该接口
public interface FactoryInterface { void say(); }
然后编写工厂类,该类包括用枚举法生产实例、通过类的全路径反射生产实例以及全路径反射加配置的方法生产实例
public class FactoryClass<T> { //枚举方法, 返回的类均实现了FactoryInterface接口 public static FactoryInterface getInstance(String key) { if("inst1".equals(key)) { return new Instance1(); } else if ("inst2".equals(key)) { return new Instance2(); } else { System.out.println("Undefined Class name: " + key + "."); return null; } } //通过全路径反射类方法 public T getInstanceByClass(String fullName) { try { T factoryInterface = (T) Class.forName(fullName).newInstance(); return factoryInterface; } catch (Exception e) { System.out.println(); e.printStackTrace(); System.out.println("Undefined Class name: " + fullName + "."); return null; } } //全路径反射加读配置方法,配置工具类略 public T getInstanceByProperites(String name) { try { T factoryInterface = (T) Class.forName(ProperiesReader.getInstance().getProperty(name)).newInstance(); return factoryInterface; } catch (Exception e) { System.out.println(); e.printStackTrace(); System.out.println("Undefined Class name: " + name + "."); return null; } } }
单元测试类
public class testFactory { @Test public void testFactory() { FactoryInterface in1 = FactoryClass.getInstance("inst1"); in1.say(); FactoryInterface in2 = FactoryClass.getInstance("inst2"); in2.say(); FactoryInterface in3 = FactoryClass.getInstance("inst3"); FactoryInterface in0 = FactoryClass.getInstance(null); FactoryClass<FactoryInterface> factoryClass = new FactoryClass<FactoryInterface>(); FactoryInterface in4 = factoryClass.getInstanceByClass("factory.Instance1"); in4.say(); FactoryInterface in5 = factoryClass.getInstanceByClass("factory.Instance2"); in5.say(); FactoryInterface in6 = factoryClass.getInstanceByClass("factory.Instance3"); } }
三、代理模式
作为某个对象的中介,提供该对象具有的部分或全部功能,并且成扩展其他功能。
常见代理模式有:远程代理、保护代理、虚拟代理、智能引用代理。
1.静态代理(代理与被代理对象已经确定,他们通常实现相同的接口或及集成相同的抽象类),实现方式有继承(子类重写与扩展,不详述)与聚合(直接调用被代理对象的方法并增加额外处理)两种方式
首先定义一个顶层接口
public interface ProxyInterface { void say(); }
然后定义一个被代理类
public class SubjectBase implements ProxyInterface { public void say() { try { Thread.sleep(1000); System.out.println("Running SubjectBase."); } catch (Exception e) { e.printStackTrace(); } } }
接着定义两个代理类
public class StaticTimeProxy implements ProxyInterface{ private ProxyInterface proxyInterface; public StaticTimeProxy(ProxyInterface proxyInterface) { this.proxyInterface = proxyInterface; } public void say() { long startTime = System.currentTimeMillis(); System.out.println("Start SubjectBase."); proxyInterface.say(); long endTime = System.currentTimeMillis(); System.out.println("End SubjectBase after " + (endTime - startTime) + "ms."); } }
public class StaticLogProxy implements ProxyInterface { private ProxyInterface proxyInterface; public StaticLogProxy(ProxyInterface proxyInterface) { this.proxyInterface = proxyInterface; } public void say() { System.out.println("Start write log."); proxyInterface.say(); System.out.println("End write log."); } }
测试类
public class TestProxy { @Test public void testStaticProxy() { SubjectBase subjectBase = new SubjectBase(); //先记录时间后记录日志 StaticLogProxy staticLogProxy1 = new StaticLogProxy(subjectBase); StaticTimeProxy staticTimeProxy1 = new StaticTimeProxy(staticLogProxy1); staticTimeProxy1.say(); //先记录日志后记录时间 StaticTimeProxy staticTimeProxy2 = new StaticTimeProxy(subjectBase); StaticLogProxy staticLogProxy2 = new StaticLogProxy(staticTimeProxy2); staticLogProxy2.say(); } }
2.JDK动态代理,只能代理实现了接口的类
定义一个InvocationHandler
public class DynamicInvocationHandler implements InvocationHandler { private Object target; public DynamicInvocationHandler(Object target) { this.target = target; } /** * * @param proxy : 被代理对象 * @param method : 被代理对象的方法 * @param args : 方法的参数 * @return : 所调用方法的返回值 * @throws Throwable */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { long startTime = System.currentTimeMillis(); System.out.println("Start SubjectBase."); method.invoke(target); long endTime = System.currentTimeMillis(); System.out.println("End SubjectBase after " + (endTime - startTime) + "ms."); return null; } }
然后生成获得一个动态代理实例并调用其中方法
public class TestProxy { @Test public void testDynamicProxy() { SubjectBase subjectBase = new SubjectBase(); InvocationHandler dynamicInvocationHandler = new DynamicInvocationHandler(subjectBase); Class<?> cls = subjectBase.getClass(); /** * loader 类加载器 * interfaces 实现接口 * h InvocationHandler */ ProxyInterface dynamicProxy = (ProxyInterface)Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), dynamicInvocationHandler); dynamicProxy.say(); } }