设计模式之单例模式

一、 Java设计模式分为哪几类?

  • 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。
  • 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。
  • 行为型模式(11种):策略模式,模板方法模式,观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

二、设计模式遵循的原则是哪几个?
有6个,分别是:

  1. 开闭原则(Open Close Principle)
    对扩展开放,对修改关闭。

  2. 里氏代换原则(Liskov Substitution Principle)
    只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。

  3. 依赖倒转原则(Dependence Inversion Principle)
    这个是开闭原则的基础,对接口编程,依赖于抽象而不依赖于具体。

  4. 接口隔离原则(Interface Segregation Principle)
    使用多个隔离的借口来降低耦合度。

  5. 迪米特法则(最少知道原则)(Demeter Principle)
    一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

  6. 合成复用原则(Composite Reuse Principle)
    原则是尽量使用合成/聚合的方式,而不是使用继承。继承实际上破坏了类的封装性,超类的方法可能会被子类修改。

三、说一下单例模式?
单例模式分为两种:懒汉模式和饿汉模式,

1. 懒汉模式:就是等到有线程调用getInstance这个方法时,才来创建对象实例。与懒汉模式相反的是饿汉模式。

双重锁检测机制确保线程安全的写法:

    public  class Singleton{
    	private static Singleton instance=null;
    	//私有构造函数
    	private Singleton(){};
        
        //双重锁检测机制
        public static Singleton  getInstance(){
        	if(instance==null){
        		synchronized(Singleton.class){
        			if(instance==null){
        				instance=new Singleton();
        			}
        		}
        	}
        	return instance;
        }
    }

进阶版:通过vlatile关键字来保证指令重排的问题

    public class Singleton {
		 private static  volatile Singleton instance = null;
 			//私有构造函数
		 private Singleton(){};

		public  static   Singleton getInstance() {
    	if (instance == null) {
       	 synchronized (Singleton.class){
            if (instance == null) {
                instance = new Singleton();
            }
        }
    }
    return instance;
   }
   }	 	
2. 饿汉模式:所谓饿汉式,就是一开始把对象实例创建出来,而不是等getInstance这个方法被调用才来创建对象。
  • 代码如下:

     public class Singleton2 {
     	 private static Singleton2 instance = new 			Singleton2();
      //私有构造器
      private Singleton2(){};
    
      public static Singleton2 getInstance() {
    		 return instance;
     }
     }	
    

采用静态内部类的写法:

public class Singleton3 {
//静态内部类
private static class LazyHolder{
    private static Singleton3 instance = new Singleton3(); 
}
//私有构造器
private Singleton3(){};
public static Singleton3 getInstance() {
    return LazyHolder.instance;
}
}

由于外部类无法访问静态内部类,因此只有当外部类调用Singleton.getInstance()方法的时候,才能得到instance实例。
并且,instance实例对象初始化的时机并不是在Singleton被加载的时候,而是当getInstance()方法被调用的时候,静态内部类才会被加载,这时instance对象才会被初始化。并且也是线程安全的。
所以,与饿汉式相比,通过静态内部类的方式,可以保证instance实例对象不会被白白浪费。但是,它仍然存在反射问题。

采用枚举的方法:

public enum Singleton4 {
//一般用大写的了,不过为了和前面的统一
//我就用小写的了

instance;
}

不过和饿汉式一样,由于一开始instance实例就被创建了,所以有可能出现白白浪费的情况。
但是,通过枚举的方式,不仅代码简单,线程安全,而且JVM还能阻止反射获取枚举类的私有构造器。
这种枚举的方式可以说的用的最多的一种方式了,唯一的缺点就是对象一开始就被创建,可能出现白白浪费没有用到对象的情况。不过,总体上,还是推荐采用枚举的方式来写.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值