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

反射技术

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方法是否能正确地返回拼接好的字符串。* 参数:无* 返回值:无*/@Testpublic void testSayHello() {ReflectServiceImpl service = ReflectServiceImpl.getInstance();String string = ReflectServiceImpl.sayHello("Tom");assertEquals("Tom", string); // 验证返回的字符串是否为"HelloTom"}/*** 测试GetInstance方法是否能返回非空的ReflectServiceImpl实例。* 参数:无* 返回值:无*/@Testpublic void testGetInstance() {ReflectServiceImpl service = ReflectServiceImpl.getInstance();assertNotNull(service); // 确保返回的实例不为空}/*** 测试GetInstance方法是否每次调用都返回相同的实例。* 参数:无* 返回值:无*/@Testpublic 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 {@Testpublic 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 {@Testpublic 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 {@Overridepublic 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 如果方法执行抛出异常,则抛出此异常。*/@Overridepublic 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动态代理创建代理对象并调用方法*/@Testpublic 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); // 设置代理对象的父类为clsenhancer.setCallback(this); // 设置回调方法为当前对象return enhancer.create(); // 创建并返回代理对象}/*** 当调用代理对象的方法时,会执行此方法。* @param proxy 代理对象* @param method 被调用的方法* @param args 方法参数* @param methodProxy 方法代理* @return 方法返回值* @throws Throwable 异常*/@Overridepublic 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的代理实例,* 然后调用代理实例的方法进行测试*/@Testpublic 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 值,通常用于决定是否继续执行目标方法*/@Overridepublic 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 方法参数数组*/@Overridepublic void after(Object proxy, Object target, Method method, Object[] args) {System.out.println("after");}/*** 在目标方法执行前后执行的方法,可以控制目标方法是否执行。* @param proxy 代理对象* @param target 目标对象* @param method 目标方法* @param args 方法参数数组*/@Overridepublic 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方法。*/@Testpublic 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 值,通常用于决定是否继续执行目标方法*/@Overridepublic boolean before(Object proxy, Object target, Method method, Object[] args) {System.out.println("MyInterceptorI反射方法前逻辑");return false; // 不反射被代理对象原有方法}/*** 在目标方法执行后执行的方法。* @param proxy 代理对象* @param target 目标对象* @param method 目标方法* @param args 方法参数数组*/@Overridepublic void after(Object proxy, Object target, Method method, Object[] args) {System.out.println("MyInterceptorI反射方法后逻辑");}/*** 在目标方法执行前后执行的方法,可以控制目标方法是否执行。* @param proxy 代理对象* @param target 目标对象* @param method 目标方法* @param args 方法参数数组*/@Overridepublic 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 值,通常用于决定是否继续执行目标方法*/@Overridepublic boolean before(Object proxy, Object target, Method method, Object[] args) {System.out.println("MyInterceptorII反射方法前逻辑");return false; // 不反射被代理对象原有方法}/*** 在目标方法执行后执行的方法。* @param proxy 代理对象* @param target 目标对象* @param method 目标方法* @param args 方法参数数组*/@Overridepublic void after(Object proxy, Object target, Method method, Object[] args) {System.out.println("MyInterceptorII反射方法后逻辑");}/*** 在目标方法执行前后执行的方法,可以控制目标方法是否执行。* @param proxy 代理对象* @param target 目标对象* @param method 目标方法* @param args 方法参数数组*/@Overridepublic 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 值,通常用于决定是否继续执行目标方法*/@Overridepublic boolean before(Object proxy, Object target, Method method, Object[] args) {System.out.println("MyInterceptorIII反射方法前逻辑");return false; // 不反射被代理对象原有方法}/*** 在目标方法执行后执行的方法。* @param proxy 代理对象* @param target 目标对象* @param method 目标方法* @param args 方法参数数组*/@Overridepublic void after(Object proxy, Object target, Method method, Object[] args) {System.out.println("MyInterceptorIII反射方法后逻辑");}/*** 在目标方法执行前后执行的方法,可以控制目标方法是否执行。* @param proxy 代理对象* @param target 目标对象* @param method 目标方法* @param args 方法参数数组*/@Overridepublic 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方法。*/@Testpublic 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类型。*/@Overridepublic 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 观察到的变动的具体内容。*/@Overridepublic 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 {/*** 测试观察者模式的功能* 无参数* 无返回值*/@Testpublic 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: product1Process finished with exit code 0

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

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

在这里插入图片描述

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

// 定义产品接口
interface Product {void produce();
}// 具体产品A
class ConcreteProductA implements Product {@Overridepublic void produce() {System.out.println("Producing Concrete Product A...");}
}// 具体产品B
class ConcreteProductB implements Product {@Overridepublic 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) {// 使用工厂方法创建并生产产品AProduct productA = ProductFactory.createProduct("A");productA.produce();// 使用工厂方法创建并生产产品BProduct productB = ProductFactory.createProduct("B");productB.produce();}
}

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

在这里插入图片描述

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

// 定义产品接口
interface Computer {void assemble();
}// 具体产品:MacComputer
class MacComputer implements Computer {@Overridepublic void assemble() {System.out.println("Assembling Mac Computer...");}
}// 具体产品:WindowsComputer
class WindowsComputer implements Computer {@Overridepublic void assemble() {System.out.println("Assembling Windows Computer...");}
}// 抽象工厂接口
interface ComputerFactory {Computer createComputer();
}// 具体工厂:MacFactory
class MacFactory implements ComputerFactory {@Overridepublic Computer createComputer() {return new MacComputer();}
}// 具体工厂:WindowsFactory
class WindowsFactory implements ComputerFactory {@Overridepublic Computer createComputer() {return new WindowsComputer();}
}//抽象工厂
package com.ssm.factory;public class ABProductFactory implements ComputerFactory{@Overridepublic 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;}@Overridepublic 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();@Overridepublic void setEngine(String engine) {sportsCar.setEngine(engine);}@Overridepublic void setTransmission(String transmission) {sportsCar.setTransmission(transmission);}@Overridepublic void setBodyType(String bodyType) {sportsCar.setBodyType(bodyType);}@Overridepublic void setSeats(int seats) {sportsCar.setSeats(seats);}@Overridepublic Car build() {return sportsCar;}
}// 具体的CarBuilder实现:SUVBuilder
class SUVBuilder implements CarBuilder {private Car suv = new Car();@Overridepublic void setEngine(String engine) {suv.setEngine(engine);}@Overridepublic void setTransmission(String transmission) {suv.setTransmission(transmission);}@Overridepublic void setBodyType(String bodyType) {suv.setBodyType(bodyType);}@Overridepublic void setSeats(int seats) {suv.setSeats(seats);}@Overridepublic 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.rhkb.cn/news/306316.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

备战蓝桥杯---刷杂题2

显然我们直接看前一半&#xff0c;然后我们按照斜行看&#xff0c;我们发现斜行是递增的&#xff0c;而同一行从左向右也是递增的&#xff0c;因此我们可以直接二分&#xff0c;同时我们发现对称轴的数为Ck,2k. 我们从16斜行枚举即可 #include<bits/stdc.h> using name…

YOLOV5训练KITTI数据集实践

目录 一、YOLOV5下载安装二、KITTI数据集三、标签格式转换四、修改配置文件五、训练六、测试 一、YOLOV5下载安装 git clone https://github.com/ultralytics/yolov5.git conda create -n yolov5 python3.8 -y conda activate yolov5 cd yolov5 pip install -r requirements.t…

一文了解ERC404协议

一、ERC404基础讲解 1、什么是ERC404协议 ERC404协议是一种实验性的、混合的ERC20/ERC721实现的&#xff0c;具有原生流动性和碎片化的协议。即该协议可让NFT像代币一样进行拆分交易。是一个图币的互换协议。具有原生流动性和碎片化的协议。 这意味着通过 ERC404 协议&#xf…

gitlab、jenkins安装及使用文档一

gitlab-jenkins安装文档 IP地址操作系统服务版本192.168.75.137Rocky9.2jenkins 2.450-1.1 jdk 11.0.22 git 2.39.3192.168.75.138Rocky9.2gitlab-ce 16.10.0 gitlab安装 前期准备: 关闭防火墙及 SELinuxsystemctl disable --now firewalld sed -i s/^SELINUXenforcing$…

谷歌seo自然搜索排名怎么提升快?

要想在谷歌上排名快速上升&#xff0c;关键在于运用GPC爬虫池跟高低搭配的外链组合 首先你要做的&#xff0c;就是让谷歌的蜘蛛频繁来你的网站&#xff0c;网站需要被谷歌蜘蛛频繁抓取和索引&#xff0c;那这时候GPC爬虫池就能派上用场了&#xff0c;GPC爬虫池能够帮你大幅度提…

短剧小程序系统开发,让短剧观看与创作更加便捷。短剧系统源码搭建

一、目前短剧发展趋势 1. 市场规模&#xff1a;根据数据来看&#xff0c;2023年中国微短剧市场规模达到了373.9亿元&#xff0c;同比上升了267.65%。预计2024年市场规模将超过500亿元。这一市场规模的增长速度非常显著&#xff0c;显示出短剧行业的巨大潜力和发展前景。 2. 投…

RabbitMQ消息模型之Fanout消息模型

Fanout消息模型 * 广播模型&#xff1a;* 一个交换机绑定多个队列* 每个队列都有一个消费者* 每个消费者消费自己队列中的消息&#xff0c;每个队列的信息是一样的生产者 package com.example.demo02.mq.fanout;import com.example.demo02.mq.util.ConnectionUtils; impor…

Python异常处理try与except跳过报错使得程序继续运行的方法

本文介绍基于Python语言的异常处理模块try与except&#xff0c;对代码中出现的报错加以跳过&#xff0c;从而使得程序继续运行的方法。 在Python语言中&#xff0c;try语句块用于包含可能引发异常的代码&#xff0c;而except语句块则用于定义在出现异常时要执行的代码。其基本结…

Windows下编译boost库

官网&#xff1a;https://www.boost.org/ 下载地址&#xff1a;https://github.com/boostorg/boost 这里使用github下载 使用git bash运行bootstrap.sh 运行b2.exe,会生成bin.v2和stage文件夹 Cmake引入

03-JAVA设计模式-适配器模式

适配器模式 设么是适配器模式 它属于结构型模式&#xff0c;主要用于将一个类的接口转换成客户端所期望的另一种接口&#xff0c;从而使得原本由于接口不兼容而无法协同工作的类能够一起工作。 适配器模式主要解决的是不兼容接口的问题。在软件开发中&#xff0c;经常会有这…

前端对接fastGPT流式数据+打字机效果

首先在对接api时 参数要设置stream: true, const data {chatId: abc,stream: true,//这里true返回流式数据detail: false,variables: {uid: sfdsdf,name: zhaoyunyao,},messages: [{ content: text, role: user }]}; 不要用axios发请求 不然处理不了流式数据 我这里使用fetch …

通过Transform与Animation,来探索CSS中的动态视觉效果

在 transform 和 animation 出现之前&#xff0c;前端开发者通常需要编写大量的 JavaScript 代码来实现动态效果。然而&#xff0c;这两个 CSS 属性的引入极大地简化了丰富动效和过渡效果的实现&#xff0c;从而让用户界面更加引人入胜&#xff0c;交互体验更为流畅。本文将深入…

详解Qt添加外部库

在Qt项目中添加外部库是一项常见任务&#xff0c;无论是静态库还是动态库都需要正确的配置才能让项目顺利编译链接。以下是详细步骤和不同场景下的配置方法&#xff1a; 方法一&#xff1a;手动编辑.pro文件 添加头文件路径&#xff1a; 在Qt项目中的.pro文件中使用INCLUDEPAT…

小程序解析二维码:jsQR

1.了解jsQR jsQR是一个纯javascript脚本实现的二维码识别库&#xff0c;不仅可以在浏览器端使用&#xff0c;而且支持后端node.js环境。jsQR使用较为简单&#xff0c;有着不错的识别率。 2.效果图 3.二维码 4.下载jsqr包 npm i -d jsqr5.代码 <!-- index.wxml --> &l…

通讯录项目(用c语言实现)

一.什么是通讯录 通讯录是一种用于存储联系人信息的工具或应用程序。它是一种电子化的地址簿&#xff0c;用于记录和管理个人、机构或组织的联系方式&#xff0c;如姓名、电话号码、电子邮件地址和邮寄地址等。通讯录的目的是方便用户在需要时查找和联系他人。 通讯录通常以列…

AI预测体彩排3第1弹【2024年4月12日预测--第1套算法开始计算第1次测试】

前面经过多个模型几十次对福彩3D的预测&#xff0c;积累了一定的经验&#xff0c;摸索了一些稳定的规律&#xff0c;有很多彩友让我也出一下排列3的预测结果&#xff0c;我认为目前时机已成熟&#xff0c;且由于福彩3D和体彩排列3的玩法完全一样&#xff0c;我认为3D的规律和模…

Zookeeper的集群搭建和ZAB协议详解

Zookeeper的集群搭建 1&#xff09;zk集群中的角色 Zookeeper集群中的节点有三个角色&#xff1a; Leader&#xff1a;处理集群的所有事务请求&#xff0c;集群中只有一个LeaderFollwoer&#xff1a;只能处理读请求&#xff0c;参与Leader选举Observer&#xff1a;只能处理读…

vscode 连接远程服务器 服务器无法上网 离线配置 .vscode-server

离线配置 vscode 连接远程服务器 .vscode-server 1. .vscode-server下载 使用vscode连接远程服务器时会自动下载配置.vscode-server文件夹&#xff0c;如果远程服务器无法联网&#xff0c;则需要手动下载 1&#xff09;网址&#xff1a;https://update.code.visualstudio.com…

MVVM架构模式

目录 MVVM 数据绑定方式 实现方式 Model View ViewModel 数据绑定方式 vue&#xff1a;&#xff1a; 数据劫持和发布-订阅模式&#xff1a; Object.defineProperty() 方法来劫持&#xff08;监控&#xff09;各属性的 getter 、setter &#xff0c;并在数据&#xff08;对…

[大模型]Qwen1.5-4B-Chat WebDemo 部署

Qwen1.5-4B-Chat WebDemo 部署 Qwen1.5 介绍 Qwen1.5 是 Qwen2 的测试版&#xff0c;Qwen1.5 是基于 transformer 的 decoder-only 语言模型&#xff0c;已在大量数据上进行了预训练。与之前发布的 Qwen 相比&#xff0c;Qwen1.5 的改进包括 6 种模型大小&#xff0c;包括 0.…