代理模式(java设计模式)

版权声明:一起学习,共同进步 https://blog.csdn.net/qq_18298439/article/details/86621678

代理模式的定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。

代理模式包含如下角色

ISubject:抽象主题角色,是一个接口。该接口是对象和它的代理共用的接口。

RealSubject:真实主题角色,是实现抽象主题接口的类。

Proxy:代理角色,内部含有对真实对象RealSubject的引用,从而可以操作真实对象。代理对象提供与真实对象相同的接口,以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

实现动态代理的关键技术是反射。
 

代理模式原理:不直接访问目标对象,而是中间加一个代理,再由代理访问真正的对象,当然代理一定实现了某些逻辑,否则就没有必要使用代理了。

1、静态代理


接口:

public interface MyInterface {
    public boolean saySomething();
 
    public boolean doSomeThint();
}


接口实现:

public class MyImpl implements MyInterface {
 
    @Override
    public boolean saySomething() {
        System.out.println("MyImpl:saySomething()");
        return true;
    }
 
    @Override
    public boolean doSomeThint() {
        System.out.println("MyImpl:doSomething()");
        return true;
    }
 
}


静态代理实现:

public class StaticProxy {
    
    // 增加了日志功能的代理类
    private static class LogProxy implements MyInterface {
 
        private MyInterface myInterface;
 
        public LogProxy(MyInterface myInterface) {
            this.myInterface = myInterface;
        }
 
        public boolean saySomething() {
            System.out.println("BeforeLog:saySomething");
            boolean tmp = myInterface.saySomething();
            System.out.println("AfterLog:saySomething");
            return tmp;
        }
 
        public boolean doSomeThint() {
            System.out.println("BeforeLog:doSomething");
            boolean tmp = myInterface.doSomeThint();
            System.out.println("AfterLog:doSomething");
            return tmp;
        }
 
    }
 
    public static void main(String[] args) {
        MyInterface inf = new LogProxy(new MyImpl());
        inf.saySomething();
        inf.doSomeThint();
    }
 
}


LogProxy是代理类,目的是在访问接口中的方法时,在方法的前后加上日志,无需修改原始实现。使用静态内部类是为了控制类的可见性。

上边的实现方法与装饰器模式的实现一模一样,只是说法不一样而已。

2、动态代理
      以上实现方式中,LogProxy只能代理MyInterface接口,它们的这种关系是编译阶段就确定的,所以称为静态代理。如果MyInterface接口修改了,那么相应的LogProxy代理也要跟着修改。

       LogProxy的逻辑是在方法的前后加上日志,它应该是独立的逻辑,与具体的接口没有关系。Java中的动态代理机制就能实现这种解耦,LogProxy到底代理谁是在运行阶段确定的,因此是动态的,代码如下:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
public class DaynamicProxy {
 
    // 增加了日志功能的代理类
    static class LogProxy implements InvocationHandler {
 
        private Object target;
 
        public LogProxy(Object target) {
            this.target = target;
        }
 
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println(proxy.getClass().getName());
            System.out.println("BeforeLog:" + method.getName());
            Object tmp = method.invoke(target, args);
            System.out.println("AfterLog:" + method.getName());
            return tmp;
        }
    }
 
    public static void main(String[] args) {
        // 到底代理谁在运行阶段指定
        InvocationHandler h = new LogProxy(new MyImpl());
        MyInterface inf = (MyInterface) Proxy.newProxyInstance(LogProxy.class.getClassLoader(),
                MyImpl.class.getInterfaces(), h);
        inf.saySomething();
        inf.doSomeThint();
    }
}


注意LogProxy实现了InvocationHandler接口,只需实现invoke一个方法就可以。
注意Proxy.newProxyInstance方法的调用,得到的MyInterface接口是被代理过的,效果与前边的实现方案相同。

不同点就是,现在LogProxy是独立的逻辑,不与具体的接口、具体的类相关,也就是它可以代理任何符合条件的类。
 

猜你喜欢

转载自blog.csdn.net/qq_18298439/article/details/86621678
今日推荐