设计模式1_反射与单例5种创建方式_懒汉式demo_饿汉式demo_静态内部方式demo_枚举单例demo_双重检测锁方式demo

反射机制

1. 什么是Java反射

就是正在运行,动态获取这个类的所有信息。

2. 反射机制的作用

1,反编译:.class–>.java
2.通过反射机制访问java对象的属性,方法,构造方法等;

反射机制的应用场景

Jdbc 加载驱动-----
Spring IOC
框架

设计模式

设计模式分类

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

1.什么是反射机制

正在运行,动态获取类的信息
java源代码—.class文件。字节码

2.使用反射机制 获取类的属性 实例化对象

spring框架。ORM.

3.构造函数 发生异常 对象不会创建成功

4.反射机制创建对象。类的完整路径

class.forName(“ ”)
forName.newinstance()

5.反射应用场景

连接jdbc
springioc 底层使用反射机制+dom4j
Hibernate spring框架 使用反射机制

6.反射机制获取

方法
forName…getMonthods()
属性
forName…getFields()

7.怎么防止反射攻击

设置私有 会没有权限 但是可以 类.setAccess(true)

8.设计模式目的:

方便维护 扩展性提高 减少冗余代码 提高可读性
降低耦合度

9.做项目

先了解需求 不要立马写代码
先思考怎么重构代码

10.如果配置文件出错了

特点:解决动态获取配置文件信息
使用分布式配置中心 使用zookeeper搭建

1.单例模式

保证在一个jvm中,只能存在一个实例,保证对象唯一性。

2.使用场景

Servlet struts2 spring(默认单例) springmvc 连接池 线程池 枚举 常量

3.单例优缺点

优点: 节约内存 重复利用 方便管理
缺点:线程安全问题

4.单例创建方式。7种

饿汉式

: 类初始化,就会加载该对象。线程安全,调用性高。
类初始化,就会创建对象。天生线程安全。可以让多个线程访问,效率高。如果不使用对象的时候,浪费内存。
new的对象存放在 永久区。垃圾回收不会回收
1.将构造函数私有化

懒汉式

:真正需要的时候才会创建该对象,具备加载功能。
天生线程不安全,需要解决线程安全问题。要加syn锁,只能一个线程访问,所以效率很低

静态内部方式:

结合懒汉饿汉优点。真正需要的时候才会创建该对象,线程安全
 优势:兼顾了懒汉模式的内存优化(使用时才初始化)以及饿汉模式的安全性(不会被反射入侵)。

劣势:需要两个类去做到这一点,虽然不会创建静态内部类的对象,但是其 Class 对象还是会被创建,而且是属于永久带的对象。

枚举单例:

实现简单 调用性高,枚举本身就是单例。
缺点: 没有延迟加载
定义常量,具备jvm保证单例 只能创建一次
可以防止反射攻击。
注意:枚举只能用@Getter 不能Data.会报错

双重检测锁方式

(jvm本质冲排序原因,会初始化多次,不建议使用)

单线程 不会发生重排序
重排序 可能会导致 创建多个对象。

代码demo

饿汉式:

public class Hungry {

    private static Hungry hungry = new Hungry();

    private  Boolean flag = false;

    //    1. 私有化 构造函数  单例防止反射
    private Hungry() {
//        Lazy.preventAttacks();
        if(!flag){
            flag = true;
        }else {
            throw new RuntimeException("已经被创建,违反单例模式。");
        }
    }

    public static Hungry getInstance() {
        return hungry;
    }


    public static void main(String[] args) {
        Hungry h1 = Hungry.getInstance();
        Hungry h2 = Hungry.getInstance();
        System.out.println(h1 == h2); // true

    }

懒汉式

public class Lazy {
    private static Lazy lazy;
    private static Boolean flag = false;

    private Lazy() {
        preventAttacks();
    }

    /**
     * 此方法在构造函数中使用
     * 单例防止反射漏洞攻击
     * 单例 只执行一次构造函数,若能进构造函数,说明还未创建对象。
     * flag改为true之后,此方法将不再被执行
     * 若进入true此判断,说明 已经被执行过一次。
     *
     */
    public static void preventAttacks() {
        if(!flag){
            flag = true;
        }else {
            throw new RuntimeException("已经被创建,违反单例模式。");
        }
    }


    public static Lazy getInstance(){
        if (lazy == null){
            lazy = new Lazy();
        }
        return lazy;
    }

    public static void main(String[] args) {
        Lazy l1 = Lazy.getInstance();
        Lazy l2 = Lazy.getInstance();
        System.out.println(l1 == l2);//true
    }
}

静态内部类

public class StaticInner {

    private static Boolean flag = false;


    private StaticInner() {
        if(!flag){
            flag = true;
        }else {
            throw new RuntimeException("已经被创建,违反单例模式。");
        }
    }

    /**
     * 静态内部类
     */
    private static class InnerDemo{
        private static StaticInner staticInner = new StaticInner();
    }

    public static StaticInner getInstance(){
        return InnerDemo.staticInner;

    }

    public static void main(String[] args) {
        StaticInner s1 = StaticInner.getInstance();
        StaticInner s2 = StaticInner.getInstance();
        System.out.println(s1 == s2);//true
    }
}

枚举

@Getter
public enum StatusEnum {

    HTTP_200(200,"成功"),
    ;

    private Integer code;

    private String msg;

    private  Boolean flag = false;


    StatusEnum() {
        if(!flag){
            flag = true;
        }else {
            throw new RuntimeException("已经被创建,违反单例模式。");
        }
    }

    StatusEnum(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public static void main(String[] args) {
        System.out.println(HTTP_200.getCode());//200
    }
}

双重锁

public class DoubleCheck {
    private static DoubleCheck doubleCheck;

    private static Boolean flag = false;

    private DoubleCheck() {
        if(!flag){
            flag = true;
        }else {
            throw new RuntimeException("已经被创建,违反单例模式。");
        }
    }

    public static DoubleCheck getInstance(){
        if(doubleCheck == null){
        //            若不加锁 假设2个线程 当是null的时候。2个都可以进来。那么1线程创建完,2又创建一次。 所以加锁后还要在判断一次。
           synchronized (DoubleCheck.class){
               if(doubleCheck == null){
                   doubleCheck = new DoubleCheck();
               }
           }
        }
        return doubleCheck;

    }

    public static void main(String[] args) {
        DoubleCheck d1 = DoubleCheck.getInstance();
        DoubleCheck d2 = DoubleCheck.getInstance();
        System.out.println(d1 == d2);
    }
}

你可能感兴趣的:(设计模式1_反射与单例5种创建方式_懒汉式demo_饿汉式demo_静态内部方式demo_枚举单例demo_双重检测锁方式demo)