代理模式Java实现


这是自己的学习总结,学习网址为:阿里云java高级开发(https://edu.aliyun.com/lesson_36_513).

基础代理设计模式

package model;

import java.lang.reflect.Constructor;

interface ISubject {
	 /**
	  * 这个接口只是简单用来实现代理模式的,可以放宽到任意接口
	  */
	void eat();
}

/**
 * 
 * @author 12872
 *
 */
class ResultSubject implements ISubject{
	@Override
	public void eat() {
		System.out.println("吃东西了");
	}
}


/**
 * 
 * @author 12872
 *
 */
class ProxyFactory {
	private ProxyFactory() {
	};
	@SuppressWarnings("unchecked")
	public static <T> T getInstance(String className) {
		T t = null;
		try {
			t = (T) Class.forName(className).newInstance();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return t;
	}
	@SuppressWarnings("unchecked")
	public static <T> T getInstance(String className,Object obj) {
		T t = null;
		try {
		//这里需要调用接口来构造,但是实际使用中,一旦接口增加
		//这里需要增加的代码量是可想而知的
			Constructor<?> cons = Class.forName(className).getConstructor(obj.getClass().getInterfaces()[0]);
			t = (T) cons.newInstance(obj);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return t;
	}
}
/**
 * 
 * @author 12872
 *
 */
class ProxySubject implements ISubject {
	private ISubject subject;
	public ProxySubject(ISubject subject) {
		this.subject = subject;
	}
	@Override
	public void eat() {
		prepare();
        this.subject.eat();
        clear();
	}
	public void prepare() {
		System.out.println("正在准备食材");
	}
	public void clear() {
		System.out.println("收拾东西");
	}
}

/**
 * 
 * @author 12872
 *
 */
public class TestDemo {
	public static void main(String[] args) {
		ISubject subject = ProxyFactory.getInstance("model.ProxySubject", ProxyFactory.getInstance("model.ResultSubject"));
		subject.eat();
	}
}

可以在这里尽可以需要通过传入一个实例和一个类名来调用,一旦有新的接口,代理模式也将要重新更改。

动态代理设计模式

package model;

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


interface ISubject {
	 /**
	  * 这个接口只是简单用来实现代理模式的,可以放宽到任意接口
	  */
	void eat();
}

/**
 * 
 * @author 12872
 *
 */
class ResultSubject implements ISubject{
	@Override
	public void eat() {
		System.out.println("吃东西了");
	}
}


/**
 * InvocationHandler,只有实现了这个,才能够实现真正的动态代理
 */
package model;

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


interface ISubject {
	 /**
	  * 这个接口只是简单用来实现代理模式的,可以放宽到任意接口
	  */
	void eat();
}

/**
 * 
 * @author 12872
 *
 */
class ResultSubject implements ISubject{
	@Override
	public void eat() {
		System.out.println("吃东西了");
	}
}


/**
 * InvocationHandler,只有实现了这个,才能够实现真正的动态代理
 */
class ProxySubject implements InvocationHandler{
	private Object target;  //绑定任意的接口对象
	/**
	 * 实现真实对象的绑定处理,同时返回代理对象
	 * @param target  
	 * @return 返回一个代理对象,根据接口动态定义
	 */
	public Object bind(String className) {
		this.target = Factory.getInstance(className);
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		return method.invoke(target, args);
	}
	
}

/**
 * 
 * @author 12872
 *
 */
public class TestDemo {
	public static void main(String[] args) {
		ISubject subject = (ISubject) new ProxySubject().bind("model.ResultSubject");
		subject.eat();
	}
}

这样子动态代理设计的大概理念就实现了,但是这里还有一些,问题,如果仅仅是这样子的实现,那么和普通的工厂类有什么区别呢,这里将在后续补充。

cglb实现动态代理

这里将实现没有接口的代理设计,但是这里需要使用一个第三方包cglb:下载地址

package model;

import java.lang.reflect.Method;

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

class Message{
	public void send() {
		System.out.println("发送消息");
	}
}

class MyProxy implements MethodInterceptor{  //定义一个拦截器
	/**
	 * 真实的代理对象
	 */
	private Object target;
	public MyProxy(Object target) {
		this.target = target;
	}
	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy metProxy) throws Throwable {
		this.prepare();
		Object ret = method.invoke(this.target, args);
		this.over();
		return null;
	}
	
	public void prepare() {
		System.out.println("电脑开机");
	}
	
	public void over() {
		System.out.println("电脑关闭");
		
	}
}

/**
 * 
 * @author 12872
 *
 */
public class ProxyModel {
	public static void main(String[] args) {
		Message message = new Message();
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(message.getClass());
		enhancer.setCallback(new MyProxy(message));
		Message temp = (Message) enhancer.create();
		temp.send();
	}
}

这种方式是一种反传统的方式,不推荐使用,只要了解就好

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值