您的位置:首页 > 其它

大话设计模式之代理模式

2018-07-25 11:49 253 查看

代理模式

  可以理解为一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。

通过代码分析理解 

//买房动作
public interface BuyHouse {
void buyHouse();
}

//客户直接买房
public class BuyHouseImpl implements BuyHouse {
@Override
public void buyHouse() {
System.out.println("我要买房子");
}
}

//通过代理(中介)买房
public class BuyHouseProxy implements BuyHouse {
BuyHouse buyHouse;

public BuyHouseProxy(BuyHouse buyHouse){
this.buyHouse=buyHouse;
}

@Override
public void buyHouse() {
System.out.println("买房前准备");
buyHouse.buyHouse();
System.out.println("买房后装修");
}
}

main测试

public class MianTest {

public static void main(String[] args){
BuyHouse buyHouse = new BuyHouseImpl();
BuyHouseProxy buyHouseProxy = new BuyHouseProxy(buyHouse);
buyHouseProxy.buyHouse();
}

}

//执行结果
买房前准备
我要买房子
买房后装修

代理模式的应用场景:

1、远程代理,也就是为一个对象在不同的地址空间提供局部代表。

2、虚拟代理,是根据需要创建开销很大的对象。通过他来存放实例化需要很长时间的真是对象。

3、安全代理,用来控制真实对象访问时的权限。

4、智能引用,是指当调用真实对象时,代理处理另外一些事。

 

2018/9/10修改

上述代理模式是基于静态代理的一种实现,那么下面来讲解基于jdk的动态代理

动态代理实现之jdk动态代理

在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。

代码实现(还是基于买房示例,现在我们只需创建一个动态代理类即可)

package com.chenpt.designModel.proxyFactory;

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

/**
* @Author: chen
* @Description: jdk的动态代理
* @Date: created in 2018/9/10
* @Modified By:
*/
public class MyProxy implements InvocationHandler {

public Object target;

MyProxy(Object target){
this.target = target;
}

/**
* @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 " + method.getName() + "++++++");
Object result = method.invoke(target,args);
System.out.println("++++++after " + method.getName() + "++++++");
return result;
}
}

  客户端

package com.chenpt.designModel.proxyFactory;
import java.lang.reflect.Proxy;

/**
* @Author: chenpengtao
* @Description:
* @Date: created in 2018/7/24
* @Modified By:
*/
public class MianTest {

public static void main(String[] args){
BuyHouse buyHouse2 = new BuyHouseImpl2();

MyProxy myProxy = new MyProxy(buyHouse2);
try {
BuyHouse subject = (BuyHouse) Proxy.newProxyInstance(myProxy.getClass().getClassLoader(),buyHouse2.getClass().getInterfaces(),myProxy);
subject.buyHouse();
} catch (Throwable throwable) {
throwable.printStackTrace();
}

}

}
//执行结果
++++++before buyHouse++++++
我要买房子2
++++++after buyHouse++++++

 

动态代理实现之cglib代理

  cglib是针对类来实现代理的,原理是对指定的业务类生成一个子类,并覆盖其中业务方法实现代理。因为采用的是继承,所以不能对final修饰的类进行代理。 

还以买房为例,现在只需实现cglib代理类即可

package com.chenpt.designModel.proxyFactory;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.context.annotation.Primary;

import java.lang.reflect.Method;

/**
* @Author: chen
* @Description: 基于cglib的动态代理
* @Date: created in 2018/9/10
* @Modified By:
*/
public class MyCglib implements MethodInterceptor{

private Object target;

//相当于JDK动态代理中的绑定
public Object getInstance(Object target) {
this.target = target;  //给业务对象赋值
Enhancer enhancer = new Enhancer(); //创建加强器,用来创建动态代理类
enhancer.setSuperclass(this.target.getClass());  //为加强器指定要代理的业务类(即:为下面生成的代理类指定父类)
//设置回调:对于代理类上所有方法的调用,都会调用CallBack,而Callback则需要实现intercept()方法进行拦
enhancer.setCallback(this);
// 创建动态代理类对象并返回
return enhancer.create();
}

@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("预处理——————");
methodProxy.invokeSuper(obj, args); //调用业务类(父类中)的方法
System.out.println("调用后操作——————");
return null;
}
}

  客户端

package com.chenpt.designModel.proxyFactory;
import java.lang.reflect.Proxy;

/**
* @Author: chenpengtao
* @Description:
* @Date: created in 2018/7/24
* @Modified By:
*/
public class MianTest {

public static void main(String[] args){
BuyHouse buyHouse2 = new BuyHouseImpl2();

MyCglib myCglib = new MyCglib();

buyHouse2 = (BuyHouse) myCglib.getInstance(buyHouse2);
buyHouse2.buyHouse();
}

}
//执行结果
预处理——————
我要买房子2
调用后操作——————

  

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: