互联网轻量级框架整合之设计模式

news2024/11/23 22:45:31

反射技术

Java的反射技术能够通过配置类的全限定名、方法和参数完成对象的初始化,甚至反射某些方法,大大的增强了Java的可配置型,这也是Spring IoC的底层原理,Java的反射技术覆盖面很广,包括对象构建、反射方法、注解、参数、接口等等,而这一切都是通过java.lang.reflect.*来完成的

通过反射构建对象

package com.ssm.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * 反射服务实现类
 */
public class ReflectServiceImpl{

    /**
     * 向指定名字的人打招呼
     * @param name 人的名字
     */
    public static string sayHello(String name)
    {
        System.out.println( "Hello"+name);
        return string;
    }

    /**
     * 获取ReflectServiceImpl类的实例
     * 通过反射获取无参构造函数创建实例
     * @return 返回ReflectServiceImpl类的实例
     */
    public static ReflectServiceImpl getInstance(){
        ReflectServiceImpl object = null;
        try {
            //通过反射获取类的无参构造函数
            Constructor<ReflectServiceImpl> constructor = ReflectServiceImpl.class.getConstructor();
            //通过构造函数创建实例
            object = constructor.newInstance();
        }catch (NoSuchMethodException|SecurityException|InstantiationException|IllegalAccessException|IllegalArgumentException| InvocationTargetException e){
            //捕获反射过程中可能抛出的异常
            e.printStackTrace();
        }
        return object;
    }
}

package com.ssm.reflect;

import org.junit.Test;
import static org.junit.Assert.*;

/**
 * ReflectServiceImpl类的测试类,用于测试其功能的正确性。
 */
public class ReflectServiceImplTest {

    /**
     * 测试sayHello方法是否能正确地返回拼接好的字符串。
     * 参数:无
     * 返回值:无
     */
    @Test
    public void testSayHello() {
        ReflectServiceImpl service = ReflectServiceImpl.getInstance();
        String string = ReflectServiceImpl.sayHello("Tom");
        assertEquals("Tom", string); // 验证返回的字符串是否为"HelloTom"
    }

    /**
     * 测试GetInstance方法是否能返回非空的ReflectServiceImpl实例。
     * 参数:无
     * 返回值:无
     */
    @Test
    public void testGetInstance() {
        ReflectServiceImpl service = ReflectServiceImpl.getInstance();
        assertNotNull(service); // 确保返回的实例不为空
    }

    /**
     * 测试GetInstance方法是否每次调用都返回相同的实例。
     * 参数:无
     * 返回值:无
     */
    @Test
    public void testSameInstance() {
        ReflectServiceImpl service1 = ReflectServiceImpl.getInstance();
        ReflectServiceImpl service2 = ReflectServiceImpl.getInstance();
        assertNotSame(service1, service2);
    }
}

package com.ssm.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * 这是一个通过反射机制实现的示例服务类,演示了如何通过反射创建实例。
 */
public class ReflectServiceImplII {
    private String name; // 姓名字段

    /**
     * 构造函数,用于初始化对象的name属性。
     *
     * @param name 传入的姓名字符串。
     */
    public ReflectServiceImplII(String name){
        this.name = name;
    }

    /**
     * 静态方法,用于打印问候语。
     *
     * @param name 传入的姓名,将被用于构造问候语。
     */
    public static void sayHello(String name)
    {
        System.out.println( "Hello"+name);
    }

    /**
     * 静态方法,用于通过反射机制创建ReflectServiceImplII的实例。
     *
     * @return 返回通过反射创建的ReflectServiceImplII实例。
     */
    public static ReflectServiceImplII getInstance(){
        ReflectServiceImplII object = null;
        try {
            // 通过反射获取带有String参数的构造函数
            Constructor<ReflectServiceImplII> constructor = ReflectServiceImplII.class.getConstructor(String.class);
            // 使用反射调用构造函数创建实例
            object = constructor.newInstance("Davie yang");
        }catch (NoSuchMethodException|SecurityException|InstantiationException|IllegalAccessException|IllegalArgumentException| InvocationTargetException e){
            e.printStackTrace();
        }
        return object;
    }
}
package com.ssm.reflect;

import org.junit.Test;
import static org.junit.Assert.*;

public class ReflectServiceImplIITest {

    @Test
    public void testGetInstance() {
        ReflectServiceImplII instance = ReflectServiceImplII.getInstance();
        instance.sayHello("Davie yang");
        assertNotNull(instance);
        assertEquals("HelloDavie yang", instance.sayHello("Davie yang"));
    }
}

反射的优点在于只要配置就可以生成对象,可以解除程序的耦合度,比较灵活,其缺点是运行相对较慢,反射技术在系统架构中的使用如何取舍是关键,Spring IoC技术就广泛的使用了发射

通过反射构建方法



package com.ssm.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 反射服务实现类,提供反射机制调用方法的功能演示
 */
public class ReflectServiceImplIII {

    /**
     * 向指定名字的人打招呼
     *
     * @param name 人的名字
     * @void 方法没有返回值
     */
    public static void sayHello(String name) {
        System.out.println("Hello" + name);
    }

    /**
     * 通过反射机制调用sayHello方法
     *
     * @return 返回反射调用方法的返回对象,本例中为null,因为sayHello方法没有返回值
     */
    public Object reflectMethod() {
        Object returnObj = null;
        ReflectServiceImplIII target = new ReflectServiceImplIII();
        try {
            // 获取sayHello方法的Method实例,包括其参数类型
            Method method = ReflectServiceImplIII.class.getMethod("sayHello", String.class);

            // 通过Method实例调用sayHello方法,传入参数"小明"  完成反射
            returnObj = method.invoke(target, "小明");
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException |
                 InvocationTargetException e) {
            // 捕获反射调用中可能出现的异常,并打印堆栈信息
            e.printStackTrace();
        }
        return returnObj;
    }
}

实例


package com.ssm.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 反射服务实现类,提供反射机制调用方法的功能演示
 */
public class ReflectServiceImplIII {

    /**
     * 向指定名字的人打招呼
     *
     * @param name 人的名字
     * @void 方法没有返回值
     */
    public static String sayHello(String name) {
        System.out.println("Hello" + name);
        return "Hello"+name;
    }

    /**
     * 通过反射机制调用sayHello方法
     *
     * @return 返回反射调用方法的返回对象,本例中为null,因为sayHello方法没有返回值
     */
    public static Object reflectMethod() {
        ReflectServiceImplIII object  = null;
        String s = null;
        try {
            Constructor<ReflectServiceImplIII> constructor = ReflectServiceImplIII.class.getConstructor();
            object = constructor.newInstance();
            // 获取sayHello方法的Method实例,包括其参数类型
            Method method = object.getClass().getMethod("sayHello", String.class);

            // 通过Method实例调用sayHello方法,传入参数"小明"
            s = (String) method.invoke(object, "小明");
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException |
                 InvocationTargetException|InstantiationException e) {
            // 捕获反射调用中可能出现的异常,并打印堆栈信息
            e.printStackTrace();
        }
        return s;
    }
}
package com.ssm.reflect;

import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class ReflectServiceImplIIITest {


    @Test
    public void testReflectMethod() {
        String result = (String) ReflectServiceImplIII.reflectMethod();
        assertEquals("Hello小明", result);
    }
}

对象在反射机制下生成后,反射了方法,如此便可以通过配置来完成对象和方法的反射,从而增强了可配置性和可扩展性,SpringIoC就是一个典型的样例

动态代理模式和责任链模式

代理模式的意义在于生成一个占位(代理对象),来代理真实对象(目标对象),从而控制真实对象的访问,动态代理和责任链无论在Spring还是在MyBatis中都有重要的应用

  • 代理对象的作用是在访问真实对象之前或者之后加入对应的逻辑,或者根据规则控制决定是否使用真实对象,因此代理必须包含两个步骤其一是建立代理对象和真实对象之间的代理关系,其二是实现代理对象的代理逻辑方法;
  • 在Java中有多种动态代理技术,比如JDK、CGLIB、Javassist、ASM等,最常用的是JDK动态代理,它是JDK自带的功能,另一种是CGLIB动态代理,这是第三方技术,在JDK的动态代理中必须使用接口而CGLIB不需要用起来更简便
  • Spring中常用JDK和CGLIB,而MyBatis还是用了Javassist

JDK动态代理

真实对象
package com.ssm.proxy;

public interface HelloWorld {
    public void sayHelloWorld();
}

package com.ssm.proxy.impl;
import com.ssm.proxy.HelloWorld;
public class HelloWorldImpl implements HelloWorld {
    @Override
    public void sayHelloWorld() {
        System.out.println("Hello World!");
    }
}

代理对象

package com.ssm.proxy.impl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;

/**
 * JDK动态代理示例类,实现InvocationHandler接口。
 * 用于创建一个代理对象,该代理对象可以在调用方法前后添加额外的操作。
 */
public class JDKProxyExample implements InvocationHandler {
    private Object target = null;

    /**
     * 绑定目标对象,返回一个代理对象。
     *
     * @param target 目标对象,将为目标对象创建一个代理。
     * @return 返回代理对象,该对象实现了目标对象的所有接口。
     */
    public Object bind(Object target) {
        this.target = target;
        // 使用JDK动态代理生成一个代理实例
        // newProxyInstance方法的三个参数意义重大,第一个是类的加载器,此处就是target的类加载器,
        // 第二个是目标对象实现的接口,此处就是target实现的所有接口
        // 第三个参数是InvocationHandler的实现类,此处用到this就是JDKProxyExample的实现类
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    /**
     * 当调用代理对象的方法时,实际上会调用此方法。
     *
     * @param proxy 代理对象本身。
     * @param method 被调用的方法。
     * @param args 方法调用时传递的参数。
     * @return 方法的返回值。
     * @throws Throwable 如果方法执行抛出异常,则抛出此异常。
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 方法执行前的操作
        System.out.println("before");
        // 调用目标对象的方法,也是通过反射实现的
        Object result = method.invoke(target, args);
        // 方法执行后的操作
        System.out.println("after");
        return result;
    }
}

在JDK动态代理中,要实现代理逻辑类必须实现java.lang.reflect.InvocathinHandler接口;如代码所示,使用bind方法完成第一步即建立代理对象和真实对象的关系;然后实现代理逻辑的方法即invoke()方法

测试代理对象
package com.ssm.proxy;

import com.ssm.proxy.impl.HelloWorldImpl;
import com.ssm.proxy.impl.JDKProxyExample;
import org.junit.Test;

/**
 * JDK动态代理测试类
 */
public class JDKProxyTest {

    /**
     * 测试使用JDK动态代理创建代理对象并调用方法
     */
    @Test
    public void testJDKProxy() {
        // 创建JDK代理示例实例
        JDKProxyExample jdkProxyExample = new JDKProxyExample();
        // 绑定真实对象并生成代理对象
        HelloWorld proxy = (HelloWorld) jdkProxyExample.bind(new HelloWorldImpl());
        // 通过代理对象调用方法
        proxy.sayHelloWorld();
    }
}

执行结果如下

before
Hello World!
after

CGLIB动态代理

    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <version>3.3.0</version>
    </dependency>
真实对象
package com.ssm.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * 反射服务实现类
 */
public class ReflectServiceImpl{

    /**
     * 向指定名字的人打招呼
     *
     * @param name 人的名字
     * @return
     */
    public String sayHello(String name)
    {
        System.out.println( "Hello"+name);
        return name;
    }

    /**
     * 获取ReflectServiceImpl类的实例
     * 通过反射获取无参构造函数创建实例
     * @return 返回ReflectServiceImpl类的实例
     */
    public static ReflectServiceImpl getInstance(){
        ReflectServiceImpl object = null;
        try {
            //通过反射获取类的无参构造函数
            Constructor<ReflectServiceImpl> constructor = ReflectServiceImpl.class.getConstructor();
            //通过构造函数创建实例
            object = constructor.newInstance();
        }catch (NoSuchMethodException|SecurityException|InstantiationException|IllegalAccessException|IllegalArgumentException| InvocationTargetException e){
            //捕获反射过程中可能抛出的异常
            e.printStackTrace();
        }
        return object;
    }
}
代理对象

package com.ssm.proxy.impl;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * Cglib代理示例类,实现了MethodInterceptor接口。
 * 用于通过Cglib动态生成代理对象。
 */
public class CglibProxyExample implements MethodInterceptor {

    /**
     * 获取代理对象。
     * @param cls 要代理的类的Class对象
     * @return 生成的代理对象
     */
    public Object getProxy(Class cls) {
        Enhancer enhancer = new Enhancer(); // 创建Enhancer对象,用于配置代理对象
        enhancer.setSuperclass(cls); // 设置代理对象的父类为cls
        enhancer.setCallback(this); // 设置回调方法为当前对象
        return enhancer.create(); // 创建并返回代理对象
    }

    /**
     * 当调用代理对象的方法时,会执行此方法。
     * @param proxy 代理对象
     * @param method 被调用的方法
     * @param args 方法参数
     * @param methodProxy 方法代理
     * @return 方法返回值
     * @throws Throwable 异常
     */
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)throws Throwable {
        // 在方法执行前打印信息
        System.out.println("before method " + method.getName());
        Object result = methodProxy.invokeSuper(proxy, args); // CGLIB反射调用真实对象方法
        // 在方法执行后打印信息
        System.out.println("after method " + method.getName());
        return result; // 返回方法结果
    }
}
测试代理对象
package com.ssm.proxy;

import com.ssm.proxy.impl.CglibProxyExample;
import com.ssm.reflect.ReflectServiceImpl;
import org.junit.Test;


/**
 * CGLIB代理测试类
 * 用于测试CGLIB动态代理的功能
 */
public class CGLIBProxyTest {

    /**
     * 测试CGLIB代理方法
     * 通过CglibProxyExample创建ReflectServiceImpl的代理实例,
     * 然后调用代理实例的方法进行测试
     */
    @Test
    public void testCGLIBProxy() {
        // 创建CglibProxyExample实例
        CglibProxyExample cpe = new CglibProxyExample();
        // 通过CglibProxyExample获取ReflectServiceImpl类的代理实例
        ReflectServiceImpl obj = (ReflectServiceImpl) cpe.getProxy(ReflectServiceImpl.class);
        // 调用代理实例的方法,并传入参数"CGLIB"
        obj.sayHello("CGLIB");

    }

}

拦截器

通常动态代理理解起来较为复杂,通常会设计一个拦截器接口供工程师使用,使用者只需要知道拦截器接口的方法、含义和作用即可,无需知道动态代理的实现过程

package com.ssm.interceptor;

/**
 * 描述了拦截器需要实现的接口。
 * 拦截器用于在指定的方法执行前、执行后或环绕执行过程中进行额外的操作。
 */
public interface Interceptor {
    
    /**
     * 在目标方法执行前执行的方法。
     * 
     * @param proxy 代理对象,即被拦截对象的代理。
     * @param target 目标对象,即被拦截的方法所在的对象。
     * @param method 被拦截的方法。
     * @param args 被拦截方法的参数数组。
     * @return 如果返回false,则阻止目标方法的执行;返回true则继续执行目标方法。
     */
    public boolean before(
            Object proxy,
            Object target,
            Method method,
            Object[] args
    );
    
    /**
     * 环绕目标方法执行的方法,可以在方法执行前、执行后、抛出异常时进行操作。
     * 
     * @param proxy 代理对象,即被拦截对象的代理。
     * @param target 目标对象,即被拦截的方法所在的对象。
     * @param method 被拦截的方法。
     * @param args 被拦截方法的参数数组。
     */
    public void around(
            Object proxy,
            Object target,
            Method method,
            Object[] args
    );
    
    /**
     * 在目标方法执行后执行的方法。
     * 
     * @param proxy 代理对象,即被拦截对象的代理。
     * @param target 目标对象,即被拦截的方法所在的对象。
     * @param method 被拦截的方法。
     * @param args 被拦截方法的参数数组。
     */
    public void after(
            Object proxy,
            Object target,
            Method method,
            Object[] args
    );
}


package com.ssm.interceptor.impl;

import com.ssm.interceptor.Interceptor;
import java.lang.reflect.Method;

/**
 * MyInterceptor 类实现了 Interceptor 接口,
 * 用于拦截器的实现,提供 before、after 和 around 方法。
 */
public class MyInterceptor implements Interceptor {

    /**
     * 在目标方法执行前执行的方法。
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数数组
     * @return 返回 boolean 值,通常用于决定是否继续执行目标方法
     */
    @Override
    public boolean before(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("before");
        return false; // 默认返回false,表示不继续执行目标方法
    }

    /**
     * 在目标方法执行后执行的方法。
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数数组
     */
    @Override
    public void after(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("after");
    }

    /**
     * 在目标方法执行前后执行的方法,可以控制目标方法是否执行。
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数数组
     */
    @Override
    public void around(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("around");
    }

}

将这些方法植入到JDK动态代理对应逻辑内

package com.ssm.interceptor.impl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
import com.ssm.interceptor.Interceptor;

/**
 * 使用JDK动态代理实现的拦截器处理类,用于生成目标对象的代理实例。
 */
public class InterceptorJdkProxy implements InvocationHandler {

    private Object target; // 目标对象,即需要被拦截的对象
    private String interceptorClass = null; // 拦截器类的全限定名

    /**
     * 构造函数,初始化目标对象和拦截器类。
     *
     * @param target 目标对象
     * @param interceptorClass 拦截器类的全限定名
     */
    public InterceptorJdkProxy(Object target, String interceptorClass) {
        this.target = target;
        this.interceptorClass = interceptorClass;
    }

    /**
     * 绑定目标对象和拦截器,返回代理对象。
     *
     * @param target 目标对象
     * @param interceptorClass 拦截器类的全限定名
     * @return 代理对象
     */
    public static Object bind(Object target, String interceptorClass){
        // 通过动态代理生成目标对象的代理实例
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                new InterceptorJdkProxy(target, interceptorClass));
    }

    /**
     * 当调用代理对象的方法时,实际执行此方法。
     *
     * @param proxy 代理对象
     * @param method 被调用的方法
     * @param args 方法参数
     * @return 方法返回值
     * @throws Throwable 方法执行中抛出的异常
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(interceptorClass == null) {
            // 如果设置了拦截器,则先执行拦截器的逻辑
            // 没有设置拦截器,直接调用目标方法
            return method.invoke(target, args);
        }
        Object result = null;
        // 通过反射实例化拦截器
        Interceptor interceptor = (Interceptor)Class.forName(interceptorClass).newInstance();
        // 调用拦截器前置方法
        if(interceptor.before(proxy, target, method, args)) {
            // 如果前置方法返回true,执行目标方法
            result = method.invoke(target, args);
        }else { // 如果前置方法返回false,执行around方法
            interceptor.around(proxy, target, method, args);
        }
        // 调用拦截器后置方法
        interceptor.after(proxy, target, method, args);
        return result;
    }
}


package com.ssm.interceptor;

import com.ssm.interceptor.impl.InterceptorJdkProxy;
import com.ssm.proxy.HelloWorld;
import com.ssm.proxy.impl.HelloWorldImpl;
import org.junit.Test;

/**
 * InterceptorJdkProxy的测试类
 * 用于测试使用JDK动态代理实现的拦截器功能
 */
public class InterceptorJdkProxyTest {

    /**
     * 测试拦截器功能
     * 通过InterceptorJdkProxy为HelloWorldImpl实例绑定拦截器MyInterceptor,
     * 然后调用代理对象的sayHelloWorld方法。
     */
    @Test
    public void testInterceptor() {
        // 使用InterceptorJdkProxy动态生成HelloWorld接口的代理类
        HelloWorld proxy = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(), "com.ssm.interceptor.impl.MyInterceptor");
        // 调用代理类的方法,会触发拦截器的逻辑
        proxy.sayHelloWorld();
    }
}

执行结果如下

反射方法前逻辑
取代了被代理对象的方法
反射方法后逻辑

Process finished with exit code 0

责任链模式

当一个对象在一个链条上被多个拦截器拦截处理(拦截器也可以选择不拦截处理)时,这样的设计模式就成为责任链模式,它适用于一个对象在多个角色中传递的场景,例如一个审批流,一个工程师请假一周,提交了审批单,需要通过3级审批,每一级都有拦截审批或者修改的审批的动作,这就需要三个拦截器,并在它们之间传递请假申请单; 而如多第一级审批修改了审批单,从而影响了后面的审批,后面的审批都要根据前面的结果进行,这个时候就需要考虑用层层代理来实现,也就是后一步的代理是基于前一步代理基础上生成的

定义三个拦截器,然后还是使用之前的JDK动态代理进行绑定和代理逻辑实现进行测试

package com.ssm.interceptor.impl;

import com.ssm.interceptor.Interceptor;

import java.lang.reflect.Method;

public class MyInterceptorI implements Interceptor {

    /**
     * 在目标方法执行前执行的方法。
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数数组
     * @return 返回 boolean 值,通常用于决定是否继续执行目标方法
     */
    @Override
    public boolean before(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("MyInterceptorI反射方法前逻辑");
        return false; // 不反射被代理对象原有方法
    }

    /**
     * 在目标方法执行后执行的方法。
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数数组
     */
    @Override
    public void after(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("MyInterceptorI反射方法后逻辑");
    }

    /**
     * 在目标方法执行前后执行的方法,可以控制目标方法是否执行。
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数数组
     */
    @Override
    public void around(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("MyInterceptorI取代了被代理对象的方法");
    }

}
package com.ssm.interceptor.impl;

import com.ssm.interceptor.Interceptor;

import java.lang.reflect.Method;

public class MyInterceptorII implements Interceptor {

    /**
     * 在目标方法执行前执行的方法。
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数数组
     * @return 返回 boolean 值,通常用于决定是否继续执行目标方法
     */
    @Override
    public boolean before(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("MyInterceptorII反射方法前逻辑");
        return false; // 不反射被代理对象原有方法
    }

    /**
     * 在目标方法执行后执行的方法。
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数数组
     */
    @Override
    public void after(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("MyInterceptorII反射方法后逻辑");
    }

    /**
     * 在目标方法执行前后执行的方法,可以控制目标方法是否执行。
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数数组
     */
    @Override
    public void around(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("MyInterceptorII取代了被代理对象的方法");
    }

}
package com.ssm.interceptor.impl;

import com.ssm.interceptor.Interceptor;

import java.lang.reflect.Method;

public class MyInterceptorIII implements Interceptor {

    /**
     * 在目标方法执行前执行的方法。
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数数组
     * @return 返回 boolean 值,通常用于决定是否继续执行目标方法
     */
    @Override
    public boolean before(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("MyInterceptorIII反射方法前逻辑");
        return false; // 不反射被代理对象原有方法
    }

    /**
     * 在目标方法执行后执行的方法。
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数数组
     */
    @Override
    public void after(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("MyInterceptorIII反射方法后逻辑");
    }

    /**
     * 在目标方法执行前后执行的方法,可以控制目标方法是否执行。
     * @param proxy 代理对象
     * @param target 目标对象
     * @param method 目标方法
     * @param args 方法参数数组
     */
    @Override
    public void around(Object proxy, Object target, Method method, Object[] args) {
        System.out.println("MyInterceptorIII取代了被代理对象的方法");
    }

}

package com.ssm.interceptor;

import com.ssm.interceptor.impl.InterceptorJdkProxy;
import com.ssm.proxy.HelloWorld;
import com.ssm.proxy.impl.HelloWorldImpl;
import org.junit.Test;

/**
 * InterceptorJdkProxy的测试类
 * 用于测试使用JDK动态代理实现的拦截器功能
 */
public class ChainTest {

    /**
     * 测试拦截器功能
     * 通过InterceptorJdkProxy为HelloWorldImpl实例绑定拦截器MyInterceptor,
     * 然后调用代理对象的sayHelloWorld方法。
     */
    @Test
    public void testInterceptorChain() {
        String packageName = "com.ssm.interceptor.impl.";
        // 使用InterceptorJdkProxy动态生成HelloWorld接口的代理类
        HelloWorld proxy1 = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(), packageName+"MyInterceptorI");
        // 调用代理类的方法,会触发拦截器的逻辑
        proxy1.sayHelloWorld();
        // 使用InterceptorJdkProxy动态生成HelloWorld接口的代理类
        HelloWorld proxy2 = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(), packageName+"MyInterceptorII");
        // 调用代理类的方法,会触发拦截器的逻辑
        proxy2.sayHelloWorld();
        // 使用InterceptorJdkProxy动态生成HelloWorld接口的代理类
        HelloWorld proxy3 = (HelloWorld) InterceptorJdkProxy.bind(new HelloWorldImpl(), packageName+"MyInterceptorIII");
        // 调用代理类的方法,会触发拦截器的逻辑
        proxy3.sayHelloWorld();

    }
}

执行结果如下

MyInterceptorI反射方法前逻辑
MyInterceptorI取代了被代理对象的方法
MyInterceptorI反射方法后逻辑
MyInterceptorII反射方法前逻辑
MyInterceptorII取代了被代理对象的方法
MyInterceptorII反射方法后逻辑
MyInterceptorIII反射方法前逻辑
MyInterceptorIII取代了被代理对象的方法
MyInterceptorIII反射方法后逻辑

Process finished with exit code 0

观察者模式

观察者模式又称为发布订阅模式,是对象的行为模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听被观察者的状态,当被观察这得状态发生了变化,会通知所有观察者自动处理各自的逻辑

package com.ssm.observer;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

public class ProductList extends Observable {
    private List<String> productList = null; //产品列表

    private static ProductList productListInstance = null; //类唯一实例

    /**
     * ProductList的私有构造方法。
     * 由于该方法被设置为私有,外部无法直接通过new关键字创建ProductList的实例。
     * 这种设计通常用于不允许外部直接实例化对象的类,或者该类仅作为工具类存在,不需实例化。
     */
    private ProductList() { // 构造方法私有化,防止外部直接实例化
    }
    /**
     * 获取ProductList的单例实例。
     * 该方法采用懒汉式单例模式,即第一次使用时才创建实例。
     * 实例在创建时会初始化一个空的产品列表,确保后续可以安全使用。
     *
     * @return 返回ProductList的单例实例。
     */
    private static ProductList getInstance() {
        if (productListInstance == null) {
            productListInstance = new ProductList();
            productListInstance.productList = new ArrayList<>();
        }
        return productListInstance;
    }


    /**
     * 向产品列表观察者模式中添加一个观察者。
     * @param observer 要添加的观察者对象,它必须实现Observer接口。
     */
    public void addProductListObserver(Observer observer) {
        this.addObserver(observer);
    }

    /**
     * 向产品列表中添加一个新产品,并通知所有观察者。
     * @param product 要添加到产品列表的新产品名称。
     */
    public void addProduct(String product) {
        productList.add(product); // 将新产品添加到产品列表中
        this.setChanged(); // 标记产品列表为已更改,通知观察者被观察者变化,触发观察者行为
        this.notifyObservers(product); // 通知所有观察者产品列表已更改,传递新产品名称作为更新信息
    }
}


package com.ssm.observer;

import java.util.Observer;
import java.util.Observable;

/**
 * XObserver类实现了Observer接口,用于观察ProductList对象的变化。
 */
public class XObserver implements Observer {

    /**
     * 当被观察的对象状态发生变化时,此方法会被调用。
     *
     * @param o 发生变化的Observable对象,这里被强制转换为ProductList类型。
     * @param product Observable对象状态变化的具体内容,这里被强制转换为String类型。
     */
    @Override
    public void update(Observable o, Object product) {
        ProductList productList = (ProductList)o; // 将Observable对象转换为ProductList类型
        String newProduct = (String)product; // 将变化的内容转换为String类型
        System.out.println("XObserver: " + newProduct); // 打印接收到的产品信息
    }
}


/**
 * YObserver类实现了Observer接口,用于观察ProductList对象的变动。
 */
package com.ssm.observer;

import java.util.Observer;
import java.util.Observable;

public class YObserver implements Observer {

    /**
     * 当被观察的对象发生变动时,此方法会被调用。
     * @param o 发生变动的Observable对象。
     * @param product 观察到的变动的具体内容。
     */
    @Override
    public void update(Observable o, Object product) {
        // 将Observable对象转换为ProductList类型,将变动内容转换为String类型
        ProductList productList = (ProductList)o;
        String newProduct = (String)product;
        // 打印接收到的产品信息
        System.out.println("YObserver: " + newProduct);
    }
}

package com.ssm.observer;

import org.junit.Test;

/**
 * 观察者模式测试类
 */
public class ObserverTest {

    /**
     * 测试观察者模式的功能
     * 无参数
     * 无返回值
     */
    @Test
    public void testObserver(){
        // 获取ProductList的实例
        ProductList observable = ProductList.getInstance();
        // 创建XObserver实例
        XObserver xObserver = new XObserver();
        // 创建YObserver实例
        YObserver yObserver = new YObserver();
        // 添加观察者
        observable.addObserver(xObserver);
        observable.addObserver(yObserver);
        // 添加产品到产品列表,触发观察者的更新
        observable.addProduct("product1");
    }
}


执行测试结果

YObserver: product1
XObserver: product1

Process finished with exit code 0

这也是解决大量if判断的一个好的方式

普通工厂模式和抽象工厂模式

在这里插入图片描述

对于需要初始化一个对象而言,有一个工厂逻辑上存在实际上也存在,只需要满足它的接口规范,便可以通过工厂去初始化(生产)一个新的对象出来,这就是普通工厂的思维

// 定义产品接口
interface Product {
    void produce();
}

// 具体产品A
class ConcreteProductA implements Product {
    @Override
    public void produce() {
        System.out.println("Producing Concrete Product A...");
    }
}

// 具体产品B
class ConcreteProductB implements Product {
    @Override
    public void produce() {
        System.out.println("Producing Concrete Product B...");
    }
}

// 工厂类
class ProductFactory {
    /**
     * 根据传入的产品类型字符串返回对应的具体产品实例
     *
     * @param type 产品类型字符串,如"A"或"B"
     * @return 返回对应的具体产品实例
     * @throws IllegalArgumentException 当传入无效的产品类型时抛出异常
     */
    public static Product createProduct(String type) throws IllegalArgumentException {
        if ("A".equals(type)) {
            return new ConcreteProductA();
        } else if ("B".equals(type)) {
            return new ConcreteProductB();
        } else {
            throw new IllegalArgumentException("Invalid product type: " + type);
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 使用工厂方法创建并生产产品A
        Product productA = ProductFactory.createProduct("A");
        productA.produce();

        // 使用工厂方法创建并生产产品B
        Product productB = ProductFactory.createProduct("B");
        productB.produce();
    }
}

在这个例子中,我们定义了一个产品接口Product以及两个实现了该接口的 concrete products:ConcreteProductA和ConcreteProductB。接着,我们创建了一个ProductFactory工厂类,它提供了一个静态方法createProduct(),根据传入的产品类型字符串返回对应的具体产品实例。客户端代码Client通过调用工厂方法来创建并操作产品,无需直接关心具体产品的创建细节,从而实现了对产品对象的解耦。这就是普通工厂设计模式的应用

在这里插入图片描述

普通工厂思维解决了一类对象的构建问题,但有时候往往类别又很多,而不是一类,因此需要更高度的抽象一层,而这种情况下对于需要初始化对象而言只需要知道一个逻辑上存在的工厂存在,而无需关心真实的工厂有多少种如何区分的怎么找到他,这就是抽象工厂思维

// 定义产品接口
interface Computer {
    void assemble();
}

// 具体产品:MacComputer
class MacComputer implements Computer {
    @Override
    public void assemble() {
        System.out.println("Assembling Mac Computer...");
    }
}

// 具体产品:WindowsComputer
class WindowsComputer implements Computer {
    @Override
    public void assemble() {
        System.out.println("Assembling Windows Computer...");
    }
}

// 抽象工厂接口
interface ComputerFactory {
    Computer createComputer();
}

// 具体工厂:MacFactory
class MacFactory implements ComputerFactory {
    @Override
    public Computer createComputer() {
        return new MacComputer();
    }
}

// 具体工厂:WindowsFactory
class WindowsFactory implements ComputerFactory {
    @Override
    public Computer createComputer() {
        return new WindowsComputer();
    }
}

//抽象工厂
package com.ssm.factory;

public class ABProductFactory implements ComputerFactory{
    @Override
    public Computer createComputer(String productNo) {
        ComputerFactory factory=null;
        if(productNo == "mac"){
            factory= (ComputerFactory) new MacFactory();
        }
        else if(productNo =="windows"){
            factory= (ComputerFactory) new WindowsFactory();
        }
        else if(productNo != null){
            factory= (ComputerFactory) new LinuxFactory();
        }
        return null;
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 使用MacFactory创建并组装Mac电脑
        ABProductFactory abProductFactory = new ABProductFactory();
        ComputerFactory macFactory = (ComputerFactory) abProductFactory.createComputer("mac");
        macFactory.createComputer("mac");

        // 使用WindowsFactory创建并组装Windows电脑
        ComputerFactory windowsFactory = (ComputerFactory) abProductFactory.createComputer("windows");
        windowsFactory.createComputer("windows");
    }
}

建造者模式

建造者模式属于对象的构建模式,可以将一个产品的内部属性与产品的生产过程分开来,从而使一个建造过程生成具有不同内部表象的产品;通过一个配置类对构建对象的步骤和参数进行统筹,然后将信息交给构建器来完成对象的构建,就是该模式的本质

// 定义Car类,表示汽车
class Car {
    private String engine;
    private String transmission;
    private String bodyType;
    private int seats;

    public String getEngine() {
        return engine;
    }

    public String getTransmission() {
        return transmission;
    }

    public String getBodyType() {
        return bodyType;
    }

    public int getSeats() {
        return seats;
    }

    protected void setEngine(String engine) {
        this.engine = engine;
    }

    protected void setTransmission(String transmission) {
        this.transmission = transmission;
    }

    protected void setBodyType(String bodyType) {
        this.bodyType = bodyType;
    }

    protected void setSeats(int seats) {
        this.seats = seats;
    }

    @Override
    public String toString() {
        return "Car{" +
                "engine='" + engine + '\'' +
                ", transmission='" + transmission + '\'' +
                ", bodyType='" + bodyType + '\'' +
                ", seats=" + seats +
                '}';
    }
}

// 定义抽象的CarBuilder接口
interface CarBuilder {
    void setEngine(String engine);
    void setTransmission(String transmission);
    void setBodyType(String bodyType);
    void setSeats(int seats);
    Car build();
}

// 具体的CarBuilder实现:SportsCarBuilder
class SportsCarBuilder implements CarBuilder {
    private Car sportsCar = new Car();

    @Override
    public void setEngine(String engine) {
        sportsCar.setEngine(engine);
    }

    @Override
    public void setTransmission(String transmission) {
        sportsCar.setTransmission(transmission);
    }

    @Override
    public void setBodyType(String bodyType) {
        sportsCar.setBodyType(bodyType);
    }

    @Override
    public void setSeats(int seats) {
        sportsCar.setSeats(seats);
    }

    @Override
    public Car build() {
        return sportsCar;
    }
}

// 具体的CarBuilder实现:SUVBuilder
class SUVBuilder implements CarBuilder {
    private Car suv = new Car();

    @Override
    public void setEngine(String engine) {
        suv.setEngine(engine);
    }

    @Override
    public void setTransmission(String transmission) {
        suv.setTransmission(transmission);
    }

    @Override
    public void setBodyType(String bodyType) {
        suv.setBodyType(bodyType);
    }

    @Override
    public void setSeats(int seats) {
        suv.setSeats(seats);
    }

    @Override
    public Car build() {
        return suv;
    }
}

// 负责协调建造过程的CarDirector类
class CarDirector {
    public Car construct(CarBuilder builder) {
        builder.setEngine("V6");
        builder.setTransmission("Automatic");
        builder.setBodyType("Sports");
        builder.setSeats(4);

        return builder.build();
    }
}

// 主程序,演示如何使用建造者模式构建汽车
public class BuilderPatternDemo {
    public static void main(String[] args) {
        CarDirector director = new CarDirector();

        CarBuilder sportsCarBuilder = new SportsCarBuilder();
        Car sportsCar = director.construct(sportsCarBuilder);
        System.out.println("Built Sports Car: " + sportsCar);

        CarBuilder suvBuilder = new SUVBuilder();
        Car suv = director.construct(suvBuilder);
        System.out.println("Built SUV: " + suv);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1589141.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux杂货铺】文件系统

目录 &#x1f308;前言&#x1f308; &#x1f4c1; 硬盘 &#x1f4c2; 物理结构 &#x1f4c2; 存储结构 &#x1f4c2; CHS定址法 &#x1f4c2; 操作系统对硬盘的管理和抽象 &#x1f4c1; 文件系统 &#x1f4c2; 分区 &#x1f4c2; 分组 &#x1f4c2; inode号 分配…

十分钟到底能不能讲明白ROS到底能做啥

总结 录完视频发现十分钟不能&#xff0c;总共花了20分钟。 提纲&#xff1a; 课程、竞赛、论文Linux、C、Python、Github和ROS关联性强平台-资格和ROS关联性弱速度-成绩路径规划-全局和局部全局-侧重路径长短-找一条最优&#xff08;短&#xff09;的路局部-侧重速度控制-用…

LeetCode-72. 编辑距离【字符串 动态规划】

LeetCode-72. 编辑距离【字符串 动态规划】 题目描述&#xff1a;解题思路一&#xff1a;动规五部曲解题思路二&#xff1a;动态规划【版本二】解题思路三&#xff1a;0 题目描述&#xff1a; 给你两个单词 word1 和 word2&#xff0c; 请返回将 word1 转换成 word2 所使用的最…

【R语言从0到精通】-3-R统计分析(列联表、独立性检验、相关性检验、t检验)

上两次教程集中学习了R语言的基本知识&#xff0c;那么我们很多时候使用R语言是进行统计分析&#xff0c;因此对于生物信息学和统计科学来说&#xff0c;R语言提供了简单优雅的方式进行统计分析。教程参考《Rlearning》 3.1 描述性统计分析 3.1.1 载入数据集及summary函数 我…

安卓一键logo设计工具_V3.6.9.1 高级版

【分析】&#xff1a;LOGO设计软件&#xff0c;可以一键生成无版权的网站LOGO等等。 网盘自动获取 链接&#xff1a;https://pan.baidu.com/s/1lpzKPim76qettahxvxtjaQ?pwd0b8x 提取码&#xff1a;0b8x

看linux内核启动流程需要的arm汇编学习笔记(二)

文章目录 一、ldr1.地址偏移模式2.变基模式3.标签3.1 访问宏定义3.2 访问一个字符串3.3 访问一个data 二、ldp和stp1.双字节加载2.双字节存储3.双字节存储的后变基模式 三、位操作1. 移位2. 按位操作3. 位段插入4.位段提取5.零计数指令 四、跳转指令1. cmp比较两个数2. cmn负向…

redis怪谈

缓存穿透、击穿、雪崩 《缓存三兄弟》 穿透无中生有key&#xff0c;布隆过滤null隔离 缓存击穿过期key&#xff0c;锁与非期解难题 雪崩大量过期key&#xff0c;过期时间要随机 面试必考三 兄 弟&#xff0c;可用限流来保底 什么是缓存穿透 指查询一个一定不存在的数据&#x…

CRMEB多商户商城系统,不止B2B2C

CRMEB多商户商城系统&#xff0c;是将多个商家汇聚到一个平台上开店&#xff0c;就像常见的京东、淘宝等。这个平台上一般包含4种不同角色&#xff0c;即平台运营管理方、入驻商家、供应商、消费者。 因为平台角色的多元化&#xff0c;多商户商城系统也具有联营、自营、招商、…

事务,MySQL函数和索引详解

文章目录 事务简介提交方式手动提交事务 事务执行流程修改事务的默认提交方式 事务原理四大特性隔离级别 MySQL函数常见的日期函数判断函数case when字符串函数数字函数 MySQL性能(了解)索引概念分类MySQL索引语法数据结构(了解)BTreeBTree好处 优缺点优势劣势 创建原则 事务简…

echarts折线图自定义打点标记小工具

由于没研究明白echarts怎么用label和lableLine实现自定义打点标记&#xff0c;索性用markPoint把长方形压扁成线模拟了一番自定义打点标记&#xff0c;记录下来备用。&#xff08;markLine同理也能实现&#xff09; 实现代码如下&#xff1a; <!DOCTYPE html> <html…

【python】在pycharm用Django写一个API接口

背景 Django是一个高级的Python Web框架&#xff0c;它鼓励快速开发和干净、实用的设计。它由经验丰富的开发者设计&#xff0c;解决了Web开发的大部分麻烦&#xff0c;因此开发者可以专注于编写应用而不是重复造轮子。Django遵循MVC设计模式&#xff0c;并拥有自带的一套便捷…

「世界看两会」南非开普敦大学教授:中非之间的信任是宝贵资产

南非开普敦大学的卡洛斯洛佩斯教授在中国日报发表的文章中强调了中非之间所建立起的信任关系的重要性&#xff0c;视其为促进双方深化合作与互利共赢的关键性资产。他认为&#xff0c;中国两会是中国和非洲国家加强合作关系、规划共同发展战略的重要时机。 洛佩斯教授指出&…

内存地产风云录:malloc、free、calloc、realloc演绎动态内存世界的楼盘开发与交易大戏

欢迎来到白刘的领域 Miracle_86.-CSDN博客 系列专栏 C语言知识 先赞后看&#xff0c;已成习惯 创作不易&#xff0c;多多支持&#xff01; 在这个波澜壮阔的内存地产世界中&#xff0c;malloc、free、calloc和realloc四位主角&#xff0c;共同演绎着一场场精彩绝伦的楼盘开…

数学知识——欧几里得算法(辗转相除法)

欧几里得算法用来求最大公约数 int gcd(int a, int b) {if(b 0) return a;else return gcd(b, a % b); } 例题&#xff1a;洛谷p1029 #include<iostream>using namespace std;#define int long long #define endl \nint x, y; int ans;int gcd(int x, int y) {if(y 0)…

C语言世界上最详细自定义类型:联合和枚举

前言&#xff1a; hello! 大家好&#xff0c;我是小陈&#xff0c;今天给大家带来一篇联合和枚举的博客&#xff01;&#xff01;&#xff01; 1.联合体类型的声明 像结构体⼀样&#xff0c;联合体也是由⼀个或者多个成员构成&#xff0c;这些成员可以不同的类型。 但是编译…

vue 文件预览

<template><div><p>打开新页面预览文件</p><div v-for"(item,index) in list" :key"index"><el-link type"primary" click"handleOpen(item.url)">{{item.name}}</el-link></div><…

Day 24 回溯理论基础 77. 组合

回溯理论基础 ​ 在递归中已经提到过了&#xff0c;回溯是递归的副产品&#xff0c;只要有递归就会有回溯&#xff1b; ​ 回溯法本质是穷举&#xff0c;穷举所有可能&#xff0c;然后选出需要的答案&#xff0c;并不是什么高效的算法&#xff1b; ​ 不高效但又不得不用&am…

Python3.7编程之病毒

基础篇 什么是病毒 病毒&#xff0c;指的是一些通过非法手段获取系统的一些权限&#xff0c;然后进行破坏或者盗取。 病毒分为两类&#xff1a; 1、破坏型 这类病毒往往会将系统弄的乱七八糟&#xff0c;比如把你的U盘删光&#xff0c;把你的系统背景调成黑客图片&#xff0c…

数据结构:线性表————单链表专题

&#x1f308;个人主页&#xff1a;小新_- &#x1f388;个人座右铭&#xff1a;“成功者不是从不失败的人&#xff0c;而是从不放弃的人&#xff01;”&#x1f388; &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f3c6;所属专栏&#xff1…

最简洁的Docker环境配置

Docker环境配置 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中&#xff0c;然后发布到任何流行的 Mac、Linux或Windows操作系统的机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间不…