揭秘设计模式之代理模式
Posted 醉酒的小男人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了揭秘设计模式之代理模式相关的知识,希望对你有一定的参考价值。
什么是代理模式
在生活中这种模式到处可见,比如租房中介、售票黄牛、婚介所、经纪人、快递、媒婆、事务代理、非侵入式日志监听等都是代理模式的实际体现。使用代理模式主要是有两个目的:一是保护目标对象,而是增强目标对象。
代理模式定义
代理模式是指为其它对象提供一种代理,以控制对这个对象的访问,属于结构型模式。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
通用写法
代理主题角色
package general;
/**
* 代理主题角色
*/
public interface ISubject {
void request();
}
真实主题角色
package general;
/**
* 真实主题角色
*/
public class RealSubject implements ISubject {
@Override
public void request() {
System.out.println("调用真实主题角色");
}
}
代理主题角色
package general;
/**
* 代理主题角色
*/
public class Proxy implements ISubject {
private ISubject subject;
public Proxy(ISubject subject) {
this.subject = subject;
}
@Override
public void request() {
before();
subject.request();
after();
}
private void before() {
System.out.println("===============方法前执行===============");
}
private void after() {
System.out.println("===============方法后执行===============");
}
}
测试类
package general;
public class GeneralTest {
public static void main(String[] args) {
Proxy proxy = new Proxy(new RealSubject());
proxy.request();
}
}
结果:
静态代理
举一个现实的例子,有些人到了结婚年龄,父母着急白了头,想各种方法到处相亲。可以用代码来实现以下。
创建IPerson类
package staticproxy;
public interface IPerson {
void findLove();
}
儿子王五要找对象,实现IPerson类:
package staticproxy;
public class WangWu implements IPerson{
@Override
public void findLove() {
System.out.println("儿子要求女孩子优秀颜值高等");
}
}
朋友李四要替王五找对象,实现IPerson类
package staticproxy;
public class LiSi implements IPerson {
private WangWu wangWu;
public LiSi(WangWu wangWu) {
this.wangWu = wangWu;
}
@Override
public void findLove() {
System.out.println("李四开始物色");
wangWu.findLove();
System.out.println("开始交往了");
}
}
测试类
package staticproxy;
public class StaticProxyTest {
public static void main(String[] args) {
LiSi liSi = new LiSi(new WangWu());
liSi.findLove();
}
}
结果
JDK动态代理
静态代理的服务对象比较单一,李四只能给王五服务,能不能有一种机构有一种通用的能力为别人服务介绍对象的。
创建代理类
package jdkproxy;
import staticproxy.IPerson;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 媒婆类
*/
public class JdkMeiPoProxy implements InvocationHandler {
private Object target;
public IPerson instance(Object target){
this.target = target;
Class<?> clazz = target.getClass();
return (IPerson) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(target,args);
after();
return result;
}
private void before() {
System.out.println("媒婆已经开始收集需求了,开始寻找中");
}
private void after() {
System.out.println("双方同意,开始交往");
}
}
创建赵六实现IPerson类
package jdkproxy;
import staticproxy.IPerson;
public class ZhaoLiu implements IPerson {
@Override
public void findLove() {
System.out.println("赵六要求有车有房");
}
}
测试类
package jdkproxy;
import staticproxy.IPerson;
import staticproxy.WangWu;
public class JdkProxyTest {
public static void main(String[] args) {
JdkMeiPoProxy jdkMeiPoProxy = new JdkMeiPoProxy();
IPerson wangwu = jdkMeiPoProxy.instance(new WangWu());
wangwu.findLove();
System.out.println("======================================");
IPerson zhaoliu = jdkMeiPoProxy.instance(new ZhaoLiu());
zhaoliu.findLove();
}
}
结果
注意:jdk是面向接口的
cglib动态代理
创建被代理类
package cglibproxy;
/**
* 单身客户
*/
public class Customer {
public void findLove(){
System.out.println("长的大方漂亮乐观");
}
}
创建代理类
package cglibproxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibMeiPoProxy implements MethodInterceptor {
public Object getInstance(Class<?> clazz){
Enhancer enhancer = new Enhancer();
//把被代理类设置成父类
enhancer.setSuperclass(clazz);
//设置拦截器CglibMeiPoProxy
enhancer.setCallback(this);
//创建并返回代理对象
return enhancer.create();
}
/**
*
* @param sub cglib生成的代理对象
* @param method 被代理对象方法
* @param objects 方法入参
* @param methodProxy 代理方法
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object sub, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object obj = methodProxy.invokeSuper(sub,objects);
after();
return obj;
}
private void before() {
System.out.println("我是媒婆,现在开始给你找对象了,根据你的要求");
System.out.println("开始查找对象");
}
private void after() {
System.out.println("如果合适的话,牵手成功");
}
}
测试类
package cglibproxy;
public class CglibMeiPoTest {
public static void main(String[] args) {
Customer customer = (Customer) new CglibMeiPoProxy().getInstance(Customer.class);
customer.findLove();
}
}
结果
JDK和CgLib动态代理区别
1.JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
2.JDK和Cglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。
3.JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。
以上是关于揭秘设计模式之代理模式的主要内容,如果未能解决你的问题,请参考以下文章