? 创建型模式:
- 单例模式, 工厂模式, 抽象工厂模式, 建造者模式, 原型模式.
? 结构型模式:
- 适配器模式, 桥接模式, 装饰模式, 组合模式, 外观模式, 享元模式, 代理模
式.
? 行为型模式:
- 模版方法模式, 命令模式, 迭代器模式, 观察者模式, 中介者模式, 备忘录模
式, 解释器模式, 状态模式, 策略模式, 职责链模式, 访问者模式.
? 常见的五种单例模式实现方式
- 主要:
? 饿汉式 (线程安全, 调用效率高. 但是, 不能延时加载.)
? 懒汉式 (线程安全, 调用效率不高. 但是, 可以延时加载.)
- 其他:
? 双重检测锁式 (由于 JVM 底层内部模型原因, 偶尔会出问题. 不建议使用)
? 静态内部类式 (线程安全, 调用效率高. 但是, 可以延时加载)
? 枚举式 (线程安全, 调用效率高, 不能延时加载. 并且可以天然的防止反射和反序列
化漏洞!)
? 如何选用?
- 单例对象 占用 资源 少, 不需要 延时加载:
? 枚举式 好于 饿汉式
- 单例对象 占用 资源 大, 需要 延时加载:
? 静态内部类式 好于 懒汉式
一: 单例模式
1.1 饿汉式
- /**
- 测试饿汉式单例模式
- */
- public class SingletonDemo1 {
- // 类初始化时, 立即加载这个对象 (没有延时加载的优势). 加载类时, 天然的是线程安全的!
- private static SingletonDemo1 instance = new SingletonDemo1();
- private SingletonDemo1(){
- }
- // 方法没有同步, 调用效率高!
- public static SingletonDemo1 getInstance(){
- return instance;
- }
- }
1.2 懒汉式
- /**
- 测试懒汉式单例模式
- */
- public class SingletonDemo2 {
- // 类初始化时, 不初始化这个对象 (延时加载, 真正用的时候再创建).
- private static SingletonDemo2 instance;
- private SingletonDemo2(){
- // 私有化构造器
- }
- // 方法同步, 调用效率低!
- public static synchronized SingletonDemo2 getInstance(){
- if(instance==null){
- instance = new SingletonDemo2();
- }
- return instance;
- }
- }
1.3 双重检查锁单例模式
- /**
- 双重检查锁实现单例模式
- */
- public class SingletonDemo3 {
- private static SingletonDemo3 instance = null;
- public static SingletonDemo3 getInstance() {
- if (instance == null) {
- SingletonDemo3 sc;
- synchronized (SingletonDemo3.class) {
- sc = instance;
- if (sc == null) {
- synchronized (SingletonDemo3.class) {
- if(sc == null) {
- sc = new SingletonDemo3();
- }
- }
- instance = sc;
- }
- }
- }
- return instance;
- }
- private SingletonDemo3() {
- }
- }
1.4 静态内部类实现单例模式
- /**
- 测试静态内部类实现单例模式
- 这种方式: 线程安全, 调用效率高, 并且实现了延时加载!
- */
- public class SingletonDemo4 {
- private static class SingletonClassInstance {
- private static final SingletonDemo4 instance = new SingletonDemo4();
- }
- private SingletonDemo4(){
- }
- // 方法没有同步, 调用效率高!
- public static SingletonDemo4 getInstance(){
- return SingletonClassInstance.instance;
- }
- }
1.5 枚举式
- /**
- 测试枚举式实现单例模式 (没有延时加载)
- */
- public enum SingletonDemo5 {
- // 这个枚举元素, 本身就是单例对象!
- INSTANCE;
- // 添加自己需要的操作!
- public void singletonOperation(){
- }
- }
1.6 懒汉式单例模式 (如何防止反射和反序列化漏洞)
- /**
- 测试懒汉式单例模式 (如何防止反射和反序列化漏洞)
- */
- public class SingletonDemo6 implements Serializable {
- // 类初始化时, 不初始化这个对象 (延时加载, 真正用的时候再创建).
- private static SingletonDemo6 instance;
- private SingletonDemo6(){
- // 私有化构造器
- if(instance!=null){
- throw new RuntimeException();
- }
- }
- // 方法同步, 调用效率低!
- public static synchronized SingletonDemo6 getInstance(){
- if(instance==null){
- instance = new SingletonDemo6();
- }
- return instance;
- }
- // 反序列化时, 如果定义了 readResolve() 则直接返回此方法指定的对象. 而不需要单独再创建新对象!
- private Object readResolve() throws ObjectStreamException {
- return instance;
- }
- }
破解单例模式 (一般情况下可以破解, 除了枚举单例模式和添加了安全措施的单例模式, 也就是上面的代码)
用反射和序列化
- /**
- 测试反射和反序列化破解单例模式
- */
- public class Client2 {
- public static void main(String[] args) throws Exception {
- SingletonDemo6 s1 = SingletonDemo6.getInstance();
- SingletonDemo6 s2 = SingletonDemo6.getInstance();
- System.out.println(s1);
- System.out.println(s2);
- // 通过反射的方式直接调用私有构造器
- // Classclazz = (Class) Class.forName("com.bjsxt.singleton.SingletonDemo6");
- // Constructorc = clazz.getDeclaredConstructor(null);
- // c.setAccessible(true);
- // SingletonDemo6 s3 = c.newInstance();
- // SingletonDemo6 s4 = c.newInstance();
- // System.out.println(s3);
- // System.out.println(s4);
- // 通过反序列化的方式构造多个对象
- FileOutputStream fos = new FileOutputStream("d:/a.txt");
- ObjectOutputStream oos = new ObjectOutputStream(fos);
- oos.writeObject(s1);
- oos.close();
- fos.close();
- ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/a.txt"));
- SingletonDemo6 s3 = (SingletonDemo6) ois.readObject();
- System.out.println(s3);
- }
- }
来源: http://www.bubuko.com/infodetail-3045777.html