设计模式学习

设计模式

1、单例模式

模式定义

        保证一个类只有一个实例,并且提供一个全局访问点

场景

        线程池、数据库连接池

类图

设计模式学习_第1张图片

懒汉模式

        延迟加载、使用的时候才进行实例化

        ①线程安全问题

        ②double check 加锁,双重检查

        ③编译器(JIT),CPU有可能对指令进行重排序,导致使用到尚未初始化的实例但已经进行引用赋值,可以通过添加volatile 关键字进行修饰,对于volatile修饰的字段,可以防止指令重排。

单线程:没有问题

package com.jason.designmode.singleton;

public class LazySingletonTest {
    public static void main(String[] args) {
        LazySingleton instance = LazySingleton.getInstance();
        LazySingleton instance1 = LazySingleton.getInstance();
        System.out.println(instance==instance1);
    }
}
class LazySingleton{
    //私有成员变量
    private static LazySingleton instance;
    //私有构造方法,防止在外部进行实例化
    private LazySingleton(){};
    public static LazySingleton getInstance(){
        if (instance==null){
            instance = new LazySingleton();
        }
        return instance;
    }
}


返回ture

多线程:出现两个不同的对象

package com.jason.designmode.singleton;

public class LazySingletonTest {
    public static void main(String[] args) {
        new Thread(()->{
            LazySingleton instance = LazySingleton.getInstance();
            System.out.println(instance);
        }).start();

        new Thread(()->{
            LazySingleton instance = LazySingleton.getInstance();
            System.out.println(instance);
        }).start();
    }
}
class LazySingleton{
    //私有成员变量
    private static LazySingleton instance;
    //私有构造方法,防止在外部进行实例化
    private LazySingleton(){};
    public static LazySingleton getInstance(){
        if (instance==null){
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance = new LazySingleton();
        }
        return instance;
    }
}

com.jason.designmode.singleton.LazySingleton@20917dd4
com.jason.designmode.singleton.LazySingleton@8124ccf

解决方法1

方法上加synchronized

问题:我们不需要每次都对这个方法进行加锁,只要确保没有实例化的时候加锁就行

package com.jason.designmode.singleton;

public class LazySingletonTest {
    public static void main(String[] args) {
        new Thread(()->{
            LazySingleton instance = LazySingleton.getInstance();
            System.out.println(instance);
        }).start();

        new Thread(()->{
            LazySingleton instance = LazySingleton.getInstance();
            System.out.println(instance);
        }).start();
    }
}
class LazySingleton{
    //私有成员变量
    private static LazySingleton instance;
    //私有构造方法,防止在外部进行实例化
    private LazySingleton(){};
    public synchronized static LazySingleton getInstance(){
        if (instance==null){
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance = new LazySingleton();
        }
        return instance;
    }
}

解决方法2:

在创建的时候加锁,并再次进行非空判断

问题:在字节码层面,可能会存在引用赋值的时候另一个线程过来了,会更加if(instance==null)进行判断,发现是有值了,直接返回instance,这时候就会造成空指针异常

解决:加volatile防止字节码重排序:1、分配空间2、引用赋值3、初始化

package com.jason.designmode.singleton;

public class LazySingletonTest {
    public static void main(String[] args) {
        new Thread(()->{
            LazySingleton instance = LazySingleton.getInstance();
            System.out.println(instance);
        }).start();

        new Thread(()->{
            LazySingleton instance = LazySingleton.getInstance();
            System.out.println(instance);
        }).start();
    }
}
class LazySingleton{
    //私有成员变量
     private volatile static LazySingleton instance;
    //私有构造方法,防止在外部进行实例化
    private LazySingleton(){};
    public synchronized static LazySingleton getInstance(){
        if (instance==null){
            synchronized (LazySingleton.class){
                if (instance==null){
                    instance = new LazySingleton();
                    //字节码层面,初始化过程123,132
                    //1.分配空间
                    //3.应用赋值
                    //2.初始化
                }

            }
        }
        return instance;
    }
}

饿汉模式

        类加载的初始化阶段完成了实例的初始化。本质就是借助于jvm类加载机制,保证实例的唯一性

类加载过程:

1.加载二进制数据到内存中,在方法区生成对应的Class数据接口

2,连接: a.验证,b.准备(给类的静态成员变量赋默认值),c.解析

3,初始化:给类的静态变量赋初值

        只有在真正使用对应的类时,才会触发初始化如( 当前类是启动类即main函数所在类,直接进行new操作,访问静态属性、访问静态方法,用反射访问类,初始化-个类的子类等)

package com.jason.designmode.singleton;

public class HungrySingletonTest {
    public static void main(String[] args) {
        HungrySingleTon instance = HungrySingleTon.getInstance();
        HungrySingleTon instance1 = HungrySingleTon.getInstance();
        System.out.println(instance==instance1);

    }
}

class HungrySingleTon{
    private static HungrySingleTon instance = new HungrySingleTon();
    private HungrySingleTon(){};
    public static HungrySingleTon getInstance(){
        return instance;
    }
}

13、观察者模式

模式定义

        定义了对象之间一对多的关系,当主题对象发生改变的时候,所依赖他的对象也会收到通知并发生改变。

        主题类:容器、添加观察者、移除观察者、通知

        接口:定义通知方法

        观察者类:实现通知方法接口

package com.jason.designmode;

import java.util.ArrayList;
import java.util.List;

/**
 * 观察者模式
 */
public class Observertest {
    public static void main(String[] args) {

        subject subject = new subject();
        Task1 task1 = new Task1();
        subject.addObserver(task1);
        Task2 task2 = new Task2();
        subject.addObserver(task2);

        subject.notifyObserver("xxxxx");
        System.out.println("--------------------");
        subject.removeObserver(task2);
        subject.notifyObserver("xxxxx");


    }
}

class subject{
    // 容器
    private List container = new ArrayList();
    // add
    public void addObserver(Observer observer){
        container.add(observer);
    }
    // remove
    public void removeObserver(Observer observer){
        container.remove(observer);
    }
    // 通知
    //当数据发生改变的时候通知观察者
    public void notifyObserver(Object object){
        for (Observer observer : container) {
            observer.update(object);
        }
    }


}


/**
 *
 * 定义为接口,因为有多个观察者实现
 */
interface Observer{
    //当主题对象发生改变的时候,被主题对象调用来通知
    void update(Object object);
}

class Task1 implements  Observer{
    @Override
    public void update(Object object) {
        System.out.println("received1:"+object);
    }
}

class Task2 implements  Observer{
    @Override
    public void update(Object object) {
        System.out.println("received2:"+object);
    }
}

优点

1.符合开闭原则,对拓展开发对修改关闭(interface Observer)

2.可以在运行时建立对象间的关系(addObserver和removeObserver)

JDK和spring中的使用

1.JDK:Observer类

2.spring:ApplicationListener类

你可能感兴趣的:(设计模式,java,android,开发语言)