单例模式
饿汉模式
首先来说一下单例模式中饿汉模式的“饿”:
什么是饿,就是保持饥饿状态,只要你需要,我就给你实例
单例模式三个要点:
- 某个类只能有一个实例(提供一个私有对象实例)
- 它必须自行创建这个实例 (私有构造函数)
- 它必须自行向整个系统提供这个实例 (私有的一个方法,用来返回这个唯一实例)
所以我们可以根据这三个点试着写出代码如下:
/**
* 1.恶汉式第一种
*/
public class SingletonTest01 {
public static void main(String[] args) {
//测试
Singleton instance=Singleton.getInstance();
Singleton instance1=Singleton.getInstance();
System.out.println(instance==instance1);//true
System.out.println(instance.hashCode()==instance1.hashCode());//true
}
}
class Singleton{
//1.构造器私有化,外部能new
private Singleton(){
}
//2.本类内创建对象实例
private final static Singleton instance=new Singleton();
//3.提供一个公有的静态方法,返回实例对象
public static Singleton getInstance(){
return instance;
}
}
当然你也可以把实例这个对象放在一个代码块里
static{//在静态代码块中
instance=new Singleton();
}
懒汉模式
懒:就是当你需要的时候,才进行创建实例
单例模式线程安全的懒汉模式,在单线程模式下面安全,在多线程下可能存在多个线程同时进行判断if(instnce==null)
**
* 起到了Lazy Loading的效果,但是只能在单线程下使用
* 如果在多线程下,一个线程进入了if(singleton==null)判断语句块,还未来得及往下执行
* ,另外一个线程也通过了这个判断语句,这时会产生多个实例,所以在多线程环境下不可使用这种方式
*/
public class Singleton03 {
public static void main(String[] args) {
Singleton instance= Singleton.getInstance();
Singleton instance1=Singleton.getInstance();
System.out.println(instance==instance1);//true
System.out.println(instance.hashCode()==instance1.hashCode());//true
}
}
//懒汉式(线程不安全)
class Singleton{
private static Singleton instnce;
private Singleton(){}
//提供一个静态的公有方法,当使用到该方法时,才去创建instance
//即懒汉式
public static Singleton getInstance(){
if(instnce==null){
instnce=new Singleton();
}
return instnce;
}
}
使用synchronizee关键字同步创建实例对象时,有且只是当前线程在进行实例化,解决了线程不安全,但是在大量线程情况下,效率太低
/**
*解决了线程不安全
* 效率太低了,每个线程想获得实例的时候,执行getInstance()方法都要进行同步
*
*/
public class Singleton04 {
public static void main(String[] args) {
Singleton instance= Singleton.getInstance();
Singleton instance1=Singleton.getInstance();
System.out.println(instance==instance1);//true
System.out.println(instance.hashCode()==instance1.hashCode());//true
}
}
//懒汉式(线程安全,同步方法)
class Singleton{
private static Singleton instnce;
private Singleton(){}
//提供一个静态的公有方法,当使用到该方法时,才去创建instance
//即懒汉式
public static synchronized Singleton getInstance(){
if(instnce==null){
instnce=new Singleton();
}
return instnce;
}
}
1、使用双重检查,第一次判断较少没有必要的同步次数;2、使用volatile关键字防止在进入synchronized代码块中指令的重排
/**
* Double-Check双重检查,判断if(singleton==null)
* 避免反复进行方法同步
* 线程安全;延迟加载;效率较高
*
*/
public class Singleton05 {
public static void main(String[] args) {
Singleton instance= Singleton.getInstance();
Singleton instance1= Singleton.getInstance();
System.out.println(instance==instance1);//true
System.out.println(instance.hashCode()==instance1.hashCode());//true
}
}
class Singleton{
private static volatile Singleton instance;
private Singleton(){}
//提供一个静态的公有方法,加入双重检查代码,解决线程安全问题,同时解决懒加载问题
//同时保证了效率,推荐使用
public static Singleton getInstance(){
if(instance==null){
synchronized (Singleton.class){
if(instance==null){
instance=new Singleton();
}
}
}
return instance;
}
}
使用类装载的机制来保证初始化实例时只有一个线程
public class Singleton06 {
public static void main(String[] args) {
Singleton instance=Singleton.getInstance();
Singleton instance1=Singleton.getInstance();
System.out.println(instance==instance1);//true
System.out.println(instance.hashCode()==instance1.hashCode());//true
}
}
class Singleton{
private static volatile Singleton instance;
private Singleton(){}
//写一个静态内部类,该类中有一个静态属性Singleton
private static class SingletonInstance{
private static final Singleton INSTANCE=new Singleton();
}
//提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
public static synchronized Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}
装饰者模式
在介绍装饰者之前,我们先看一下它是由哪几个部件组成的
**Component(抽象构件):**它是具体构件和抽象装饰类的共同父类,(抽象装饰类的父类意思就是:抽象装饰类继承了这个抽象组件类)
**ConcreteComponent(具体构件):**抽象构件类子类
Decorator:抽象装饰类
**ConcreteDecorator(具体装饰类):**抽象装饰类子类
桥接模式
系统中存在两个变化的维度记住这点,你就记住了桥接模式
手机牌子:摩托罗拉、小米、OPPO
手机构架类型:翻盖、触屏、直板
还是先来介绍其中的几个角色:
**Abstraction(抽象类):**用于定义抽象类的接口,通常是抽象类,不是接口。记住这个类是组合了抽象接口(也就是合并了另外一个维度)
**RefinedAbstraction(扩充抽象类):**继承抽象类
**Implementor(实现类接口):**与Abstraction接口不一致,另外一个维度
**ConcreteImplementor(具体实现类):**实现了Implementor
观察者模式
老样子,我们先来看几个角色,记住这些角色,慢慢体会,你就会理解这几个设计模式,在心里面自己可以举例子
观察者模式怕是比较好理解的了,红绿灯和你嘛,红绿灯变换一个状态,在你的眼球里然后更新,你察觉到,完事
**Subject(目标):**红绿灯,被观察的对象
**ConcreteSubject(具体目标):**被观察目标类的子类,警察的手势也可能会被你看哦
**Observer(观察者):**人
**ConcreteObserver(具体观察者):**你或者你大爷
在具体的目标类中存放了具体的观察者集合,当具体的目标实例变换状态时,也会更新观察者的状态
这里给读者建议:可以学习刘伟的设计模式,或者是韩顺平的设计模式(B站上有),感觉韩老师也是照着这本书来讲的。