refactoringguru,sourcemaking。
创建型模式
单例模式
- 提前创建单例:适用于频繁使用,或者单例占用资源较少的情况。最简单创建单例的方式是使用枚举类。
- 延迟创建单例:存在多线程问题,可以直接使用
synchronized
对整个方法进行同步。但实际上只有在第一次调用时才需要同步,所以更优的实现是使用双重检查加锁以及 volatile
关键字。
- 当使用多个类加载器、反射和序列化/反序列化时,要注意避免创建多个单例实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public final class Singleton {
private volatile static Singleton instance; public String value;
private Singleton(String value) { this.value = value; }
public static Singleton getInstance(String value) { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(value); } } } return instance; } }
|
结构型模式
代理模式
Java 在 java.lang.reflect
包中有自己的代理支持,利用该包可以动态地创建代理类,所以该技术被称为动态代理。
- 实现
InvocationHandler
接口。
- 以指定的对象和
InvocationHandler
实现类为参数,调用 Proxy.newProxyInstance
方法,创建代理对象。
- 将代理对象强制类型转换为指定的对象所实现的某个接口类型,然后调用方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| interface Person {
void foo(); }
class PersonImpl implements Person {
@Override public void foo() { System.out.println(this.getClass().getName()); } }
class MyInvocationHandler implements InvocationHandler {
private Person person;
public MyInvocationHandler(Person person) { this.person = person; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(this.getClass().getName()); return method.invoke(person, args); } }
class ProxyFactory {
public static Person getProxyInstance(Person person) { return (Person) Proxy.newProxyInstance( person.getClass().getClassLoader(), person.getClass().getInterfaces(), new MyInvocationHandler(person)); } }
public class DynamicProxy {
public static Person getProxyInstance(Person person) { return (Person) Proxy.newProxyInstance( person.getClass().getClassLoader(), person.getClass().getInterfaces(), new MyInvocationHandler(person)); }
public static void main(String[] args) { Person person = new PersonImpl(); Person proxyInstance = getProxyInstance(person); proxyInstance.foo(); } }
|