《Head First 设计模式》(十三):代理模式

1. 简介

1.1 定义

为另一个对象提供一个替身或占位符以访问这个对象。

1.2 模式角色
  • Subject 抽象主题角色:声明了目标对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象。
  • RealSubject 具体主题角色:也叫做被委托角色、被代理角色。是业务逻辑的具体执行者。
  • Proxy 代理主题角色:代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象;代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象。
1.3 角色关系图

在这里插入图片描述

1.4 模式分类
  • 静态代理:由程序员创建或特定工具自动生成源代码,在对其编译。在程序员运行之前,代理类.class文件就已经被创建了。
  • 动态代理:在程序运行时通过反射机制动态创建的。

2. 代码示例

2.1 静态代理

Subject 抽象主题:

package com.jbp.designpattern.proxy;

/**
 * @ClassName: UserService
 * @description: 用户服务
 * @author: JiangBeiPing
 * @create: 2021-09-09 16:04
 * @Version: 1.0
 **/
public interface UserService {

    void userLogin();

}

RealSubject 具体主题:

package com.jbp.designpattern.proxy;

/**
 * @ClassName: UserServiceImpl
 * @description: 用户服务实现类
 * @author: JiangBeiPing
 * @create: 2021-09-09 16:06
 * @Version: 1.0
 **/
public class UserServiceImpl implements UserService{

    @Override
    public void userLogin() {
        System.out.println("用户开始登陆...");
    }
}

Proxy 代理主题:

package com.jbp.designpattern.proxy;

/**
 * @ClassName: UserServiceProxy
 * @description: 用户服务代理类
 * @author: JiangBeiPing
 * @create: 2021-09-09 16:07
 * @Version: 1.0
 **/
public class UserServiceProxy implements UserService{

    private UserService userService;

    public UserServiceProxy(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void userLogin() {
        System.out.println("登陆之前...");
        userService.userLogin();
        System.out.println("登陆之后...");
    }
}

2.2 动态代理

Proxy 代理主题:

package com.jbp.designpattern.proxy;

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

/**
 * @ClassName: DynamicProxyHandler
 * @description: 动态代理处理器
 * @author: JiangBeiPing
 * @create: 2021-09-09 16:17
 * @Version: 1.0
 **/
public class DynamicProxyHandler implements InvocationHandler {

    private Object object;

    public DynamicProxyHandler(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("登陆之前...");
        Object result = method.invoke(object, args);
        System.out.println("登陆之后...");
        return result;
    }
}

2.3 Cglib代理代理

Proxy 代理主题:

package com.jbp.designpattern.proxy;

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

import java.lang.reflect.Method;

/**
 * @ClassName: CglibProxy
 * @description: Cglib代理
 * @author: JiangBeiPing
 * @create: 2021-09-09 16:25
 * @Version: 1.0
 **/
public class CglibProxy implements MethodInterceptor {

    private Object target;

    public Object getInstance(final Object target){
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("登陆之前...");
        Object result = methodProxy.invokeSuper(object, args);
        System.out.println("登陆之后...");
        return result;
    }
}

测试:

package com.jbp.designpattern.proxy;

import java.lang.reflect.Proxy;

/**
 * @ClassName: Client
 * @description: 测试
 * @author: JiangBeiPing
 * @create: 2021-09-09 16:09
 * @Version: 1.0
 **/
public class Client {
    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();

        // 无代理
        userService.userLogin();

        System.out.println("代理之后...");

        // 静态代理
        UserServiceProxy userServiceProxy = new UserServiceProxy(userService);
        userServiceProxy.userLogin();

        // 动态代理
        UserService dynamicProxy = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserService.class}, new DynamicProxyHandler(userService));
        dynamicProxy.userLogin();

        // Cglib代理
        CglibProxy cglibProxy = new CglibProxy();
        UserServiceImpl instance = (UserServiceImpl) cglibProxy.getInstance(userService);
        instance.userLogin();
    }
}

3. 总结

3.1 静态代理

优点:

  • 可以做到在符合开闭原则的情况下对目标对象进行功能扩展。

缺点:

  • 要为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。
3.2 动态代理

优点:

  • 需要的类少了。
  • 代理内容也就是InvocationHandler接口的实现类可以复用。
  • 可以在不修改原来代码的基础上,就在原来代码的基础上做操作,即AOP,面向切面编程。

缺点:

  • 只能针对接口生成代理,不能只针对某一个类生成代理。
3.3 CGLIB代理

优点:

  • CGLIB创建的动态代理对象比JDK创建的动态代理对象的性能更高。

缺点:

  • CGLIB创建代理对象时所花费的时间却比JDK多得多。
  • CGLib由于是采用动态创建子类的方法,对于final修饰的方法无法进行代理。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值