设计模式之代理模式

本文详细介绍了设计模式中的代理模式,包括静态代理和动态代理的实现方式,并通过实例展示了如何使用代理模式解决问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

设计模式之代理模式

代理模式(Proxy) 为其他对象提供一个代理以控制对这个对象的访问。

代理模式实现又分静态代理和动态代理。

结构图

代码示例

静态代理


需求:某一天,我和朋友老王聚会时,看见他的朋友娇妹很漂亮,想追求她。但是我又不好意思直接和娇妹打招呼,就想通过老王进行介绍认识。


实现时目标类和代理类实现同一个接口即可。

首先,定义打招呼的接口

public interface IMeetGirl {
String sayHello();

String doMyGirlFriend();
}

真实的请求对象我:

public class Me implements IMeetGirl {

private BeautifulGirl girl;

public Me(BeautifulGirl girl) {
    this.girl = girl;
}

//定义真实的行为
@Override
public String sayHello() {

    return girl.getName()+" 你好,我是一个大帅比!";

}

@Override
public String doMyGirlFriend() {

    return girl.getName()+" 做我女朋友吧!";
}
}

代理对象老王:

public class LaoWang implements IMeetGirl {

private Me me;

public LaoWang(BeautifulGirl girl) {

    me = new Me(girl);
}

//在代理方法中调用真实的方法
@Override
public String sayHello() {
    return me.sayHello();
}

@Override
public String doMyGirlFriend() {
    return me.doMyGirlFriend();
}
}

实体类

public class BeautifulGirl {

private String name;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
}

public class test {

public static void main(String[] args) {

    BeautifulGirl girl = new BeautifulGirl();
    girl.setName("娇妹");

    LaoWang proxy = new LaoWang(girl);

    System.out.println(proxy.sayHello());
    System.out.println(proxy.doMyGirlFriend());
    //娇妹 你好,我是一个大帅比!
    //娇妹 做我女朋友吧!
}
}

这样,我们就通过老王成功的向娇妹打招呼了。


动态代理

在Spring中,AOP的实现离不开动态代理。而实现动态代理又可通过jdk或者cglib来实现。
jdk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。

JDK动态代理

使用jdk动态代理需要基于接口编程

public interface HelloService {

    void sayHello();
}
public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello() {
        System.out.println("Hello World!");
    }
}
/**
 * 使用此种方法动态代理对象需要基于接口编程
 */
public class HelloServiceJdkProxyFactory implements InvocationHandler {


    //需要被代理的目标对象
    private HelloService helloService;

    public HelloServiceJdkProxyFactory(HelloService helloService) {
        this.helloService = helloService;
    }

    //生成代理对象
    public HelloService newProxyInstance() {

        /**
         * loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
         interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
         h:一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
         */

        return (HelloService) Proxy.newProxyInstance(helloService.getClass().getClassLoader(),
                helloService.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 hello world");
        //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
        Object o = method.invoke(helloService, args);
        System.out.println("after hello world");
        return o;
    }
}
   @Test
    public void jdkProxyTest() {

        HelloService helloService = new HelloServiceImpl();
        HelloServiceJdkProxyFactory proxy = new HelloServiceJdkProxyFactory(helloService);
        proxy.newProxyInstance().sayHello();     
    }

测试结果:
before hello world
Hello World !
after hello world


CGlib动态代理
/**
 * Cglib动态代理,需要cglib包和asm依赖包
 **/
public class HelloServiceCglibProxyFactory implements MethodInterceptor {


    public Object newProxyInstance(Class c) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(c);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        System.out.println("before hello world");
        Object invoke = methodProxy.invokeSuper(o, objects);
        System.out.println("after hello world");
        return invoke;
    }
}
    @Test
    public void cglibProxyTest() {

        HelloServiceCglibProxyFactory proxy = new HelloServiceCglibProxyFactory();
        HelloService helloService = (HelloService) proxy.newProxyInstance(HelloServiceImpl.class);
        helloService.sayHello();
    }

测试结果:
before hello world
Hello World !
after hello world


那么什么样的需求时候适合使用代理模式呢?

代理模式的使用场景:

  • 远程代理:也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。

  • 虚拟代理:如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。通过它来存放需要很长时间的真实对象

  • 安全代理:控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。

  • 智能代理,指当调用真实的对象时,代理处理另外一些事。如计算真实对象的引用次数,当该对象没有引用时,可以自动释放它。


源码链接

本文地址:http://blog.youkuaiyun.com/ProdigalWang/article/details/75675756

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值