IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java设计模式以及案例 - 持续输出中 -> 正文阅读

[Java知识库]Java设计模式以及案例 - 持续输出中

前言

Java设计模式

一、单例模式

饿汉式

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return instance;
    }

}

这是实现一个安全的单例模式的最简单粗暴的写法,这种实现方式我们称之为饿汉式。之所以称之为饿汉式,是因为肚子很饿了,想马上吃到东西,不想等待生产时间。这种写法,在类被加载的时候就把Singleton实例给创建出来了。
饿汉式的缺点就是,可能在还不需要此实例的时候就已经把实例创建出来了,没起到lazy loading的效果。优点就是实现简单,而且安全可靠。

懒汉式

public class Singleton {
    
    private static Singleton instance;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    
}

相比饿汉式,懒汉式显得没那么“饿”,在真正需要的时候再去创建实例。在getInstance方法中,先判断实例是否为空再决定是否去创建实例,看起来似乎很完美,但是存在线程安全问题。在并发获取实例的时候,可能会存在构建了多个实例的情况。所以,需要对此代码进行下改进。

public class SingletonSafe {

    private static volatile SingletonSafe singleton;

    private SingletonSafe() {
    }

    public static SingletonSafe getSingleton() {
        if (singleton == null) {
            synchronized (SingletonSafe.class) {
                if (singleton == null) {
                    singleton = new SingletonSafe();
                }
            }
        }
        return singleton;
    }
}

这里采用了双重校验的方式,对懒汉式单例模式做了线程安全处理。通过加锁,可以保证同时只有一个线程走到第二个判空代码中去,这样保证了只创建 一个实例。这里还用到了volatile关键字来修饰singleton,其最关键的作用是防止指令重排。

枚举

在effective java(这本书真的很棒)中说道,最佳的单例实现模式就是枚举模式。利用枚举的特性,让JVM来帮我们保证线程安全和单一实例的问题。除此之外,写法还特别简单。

public enum Singleton {

    INSTANCE;

    public void doSomething() {
        System.out.println("doSomething");
    }

}

============================
    
public class Main {

    public static void main(String[] args) {
        Singleton.INSTANCE.doSomething();
    }

}

静态内部类

public class Singleton {

    private static class SingletonHolder {
        private static Singleton instance = new Singleton();
    }

    private Singleton() {
        
    }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}

二、代理模式

语雀:Java静态代理和动态代理(JDK、cglib)

1、Java静态代理

代码是写死的。

以相亲(blinddate)为例:

1.定义一个接口

 interface Subject{
     public void blindDate(String s);
 }

2.定义委托类

class Person implements Subject{
    public void blindDate(String s){    
        System.out.println("i am blinddating with "+s);     
    }
}

3.定义代理

class DatgingAgency implments Subject{  
    private Subject target;//受代理者,委托者,代理类需要知道代理谁,代谁做事  
    public DatgingAgency(Subject target){  
        this.target=target;  
    } 
    public String beforeBlindDate(String s){  
        return s;//寻找匹配者
    }
    public void blindDate(String s){
        String s=beforeBlindDate(String s); 
        target.blindDate(s);//相亲由委托类自己来进行 
    }
}

4.测试

public static void main(args[]){ 
    Person p=new Person();
    DatingAgency da=new DatingAgency(p);
    da.blindDate("志林姐姐")}

总结:静态代理,说白了就是代理类已经写死了,程序在运行期需要加载代理类时,将事先在本地编译(或者其他方式)好的class文件加载到JVM供虚拟机使用。静态代理需要开发者自己去实现。

2、JDK动态代理

源于Java设计模式中的代理模式。
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
如果是纯代理模式的案例,那么代理对象WanMeiLiProxy实现的是Gril接口。
为什么使用代理模式(什么场景会使用代理模式)
添加日志、判断权限、事务、、、、、、

反射技术

在这里插入图片描述
在这里插入图片描述

动态代理运用了大量反射机制,首先简单看看反射的运用:

JDK动态代理示例

代理的是接口。

(1)定义接口
  public interface Girl {
      
      void date();
      
      void watchMovie();
  }
(2)真实对象

定义委托类,委托类是真正的执行者

  public class WangMeiLi implements Girl{
  
      @Override
      public void date() {
          // TODO Auto-generated method stub
          System.out.println("我是王美丽");
      }
  
      @Override
      public void watchMovie() {
          // TODO Auto-generated method stub
          System.out.println("喜欢看电影");
      }
  
  }
(3)代理对象(处理器对象)

首先介绍Java中关于动态代理的两个主要接口和类;
java.lang.reflect.Proxy[?prɑ?ksi] :这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
// 最主要的方法:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
// 该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象
// 第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行
Object invoke(Object proxy, Method method, Object[] args)

定义一个实现了InvocationHandler接口的类,这个类须绑定目标对象(即委托类),并利用Proxy的静态方法返回动态代理类的实例

  public class WanMeiLiProxy implements InvocationHandler{
      
      Girl girl;
      
      public WanMeiLiProxy(Girl girl) {
          // TODO Auto-generated constructor stub
          this.girl = girl;
      }
   
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          System.out.println("前置增强");
         //用到了反射机制
          method.invoke(girl, args);
          System.out.println("后置增强");
          return null;
      }
  }
(4)调用端
  public class ProxyTest {
  
      public static void main(String[] args) {
          //被代理对象
          WangMeiLi wangMeiLi = new WangMeiLi();
          //代理类
          WanMeiLiProxy wanMeiLiProxy = new WanMeiLiProxy(wangMeiLi);
        // 得到代理对象 (被代理对象的类加载器,被代理对象的接口,被代理对象的代理类)
          Girl girl = (Girl) Proxy.newProxyInstance(wangMeiLi.getClass().getClassLoader(), wangMeiLi.getClass().getInterfaces(), wanMeiLiProxy);
          girl.date();
  
      }
  }

3、Cglib动态代理

Cglib动态代理是针对代理的类, 动态生成一个子类, 然后子类覆盖代理类中的方法, 如果是private或是final类修饰的方法,则不会被重写。
CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-04 10:54:21  更:2022-02-04 10:54:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:06:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码