设计模式之代理模式

代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。
比如我们想请一个电影明星(目标类)演电影,不直接找明星来,而是联系他的经纪人(代理类),代理会在明星表演的基础上增加功能,比如安排行程、谈薪资、收钱等。

1. 静态代理

在静态代理中,要求目标类和代理类实现同一个接口或者继承同一个父类。

//演员接口
public interface Actor {
	void play();//表演
}
//电影明星类
public class MovieActor implements Actor {
	@Override
	public void play() {
		System.out.println("电影演员演电影");
	}
}
//经纪人类
public class Agent implements Actor{
	private Actor actor;//经纪人代理的明星
	
	public Agent() {
		super();
		this.actor = new MovieActor();
	}

	@Override
	public void play() {
		System.out.println("经纪人安排酒店住宿谈薪资");
		actor.play();//目标对象的方法
		System.out.println("经纪人收钱");
	}
}
//测试方法
	public static void main(String[] args) {
		Actor agent=new Agent();//通过经纪人去联系
		agent.play();
	}

测试方法中不直接使用演员类,而是通过经纪人的类,我们在演员表演的基础上增加了安排酒店和收钱的环节。它的好处是在不改变目标类的基础上增加额外的功能。但缺点是代理类和目标类必须实现同样的接口,当接口中增加方法时要同时修改目标类和代理类。

2. 动态代理

2.1 JDK代理

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

public class JDKProxy {
	private MovieActor target;

	public JDKProxy() {
		super();
		this.target = new MovieActor();
	}

	public Object getProxyInstance() {
		Class clazz = target.getClass();//使用反射
		return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				System.out.println("谈薪资");
				// 执行目标对象方法
				Object returnValue = method.invoke(target, args);
				System.out.println("收钱");
				return returnValue;
			}
		});
	}
}
// 测试方法
	public static void main(String[] args) {
		JDKProxy proxy = new JDKProxy();
		Actor actor=(Actor) proxy.getProxyInstance();
		actor.play();
	}

2.2 Cglib代理

如果目标对象没有实现接口,就不能使用JDK代理,可以使用Cglib代理,也叫做子类代理。使用Cglib需要引入额外的jar包。

import java.lang.reflect.Method;

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

public class CglibProxy implements MethodInterceptor{

	//维护目标对象
    private Object target;

    public CglibProxy() {
        this.target = new MovieActor();
    }

    //给目标对象创建一个代理对象
    public Object getProxyInstance(){
        Enhancer en = new Enhancer();//1.工具类
        en.setSuperclass(target.getClass());//2.设置父类
        en.setCallback(this);//3.设置回调函数
        return en.create(); //4.创建子类(代理对象)
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("谈薪资...");
        //执行目标对象的方法
        Object returnValue = method.invoke(target, args);
        System.out.println("收钱...");
        return returnValue;
    }

}

// 测试方法
	public static void main(String[] args) {
		CglibProxy proxy = new CglibProxy();
		Actor actor=(Actor) proxy.getProxyInstance();
		actor.play();
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

专治八阿哥的孟老师

您的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值