设计模式

代理模式

2019-07-11  本文已影响6人  dlihasa

代理模式的定义

为其他对象提供一种代理以控制对这个对象的访问。

代理模式的使用场景

当无法或不想直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口。

代理模式的分类

代理模式分为静态代理和动态代理。静态代理的代码是由开发者自己写的代码,也就是说我们的代码运行前代理类的class编译文件就已经存在,而动态代理不同,动态代理是通过反射机制动态地生成代理者的对象,也就是说我们在编码阶段不需要知道代理的是谁,而是在运行阶段决定代理谁。

代理模式实现举例:

(1)静态代理实现:

public interface ISinger {
    void sing();
}
public class Singer implements ISinger{

    @Override
    public void sing() {
        System.out.println("开始演唱");
    }

}
public class SingerProxy implements ISinger{
    
    private ISinger target;
    
    public SingerProxy(ISinger target){
        this.target = target;
    }
    
    @Override
    public void sing(){
        System.out.println("唱之前的一些动作");
        target.sing();
        System.out.println("唱之后的一些动作");
    }
}
public class ProxyTest {
    public static void main(String[] args){
        Singer singer = new Singer();
        SingerProxy proxy = new SingerProxy(singer);
        proxy.sing();
    }
}

首先一个具有某项功能的接口或者抽象类,然后被代理类实现接口具体实现功能,代理类实现接口,并持有被代理类的对象,在实现接口方法中调用被代理类的相应方法,当然在调用之前或者之后代理类可以根据自己的需要选择是否加入一些逻辑。
(2)动态代理实现:

public interface ISinger {
    void sing();
}
public class Singer implements ISinger{

    @Override
    public void sing() {
        System.out.println("开始演唱");
    }

}
public class DynamicProxy implements InvocationHandler{
    
    private Object target;
    
    public DynamicProxy (Object target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         //  在代理真实对象前我们可以添加一些自己的操作
        System.out.println("Method:" + method);
        System.out.println("唱之前的一些动作");
        //执行目标对象方法
        Object returnObj =  method.invoke(target, args);
        System.out.println("唱之后的一些动作");
        return returnObj;
    }

}
public class DynamicProxyTest {

    public static void main(String[] args) {
        //被代理对象
        Singer target = new Singer();
        //构造一个动态代理类(可以传入任何一个被代理对象构造)
        DynamicProxy p = new DynamicProxy (target);
        //之前传入的是一个Singer被代理对象,所以这里构造了一个Singer的代理对象
        ISinger proxy = (ISinger) Proxy.newProxyInstance(target.getClass().getClassLoader(), 
                target.getClass().getInterfaces(), p);
        proxy.sing();
    }

}

输出:

com.sun.proxy.$Proxy0
Method:public abstract void dynamicProxy.ISinger.sing()
唱之前的一些动作
开始演唱
唱之后的一些动作

动态代理通过一个代理类来代理N个被代理对象,其实质是对代理者和被代理者进行解耦,使两者没有直接的耦合关系。相对于静态代理则只能为给定接口下的实现类做代理,如果接口不同就需要重新定义不同的代理类,较为麻烦。
参考:
JDK动态代理实现原理---推荐
http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/index.html)
https://www.cnblogs.com/xiaoluo501395377/p/3383130.html
https://www.cnblogs.com/flyoung2008/p/3251148.html

上一篇 下一篇

猜你喜欢

热点阅读