java实现23种设计模式之代理模式
看代码:
package com.ceshi7; public interface Sourceable { public void method(); }
package com.ceshi7; public class Source implements Sourceable{ @Override public void method() { System.out.println("这是原方法!"); } }
package com.ceshi7; public class Proxy implements Sourceable{ private Source source; public Proxy(){ super(); this.source = new Source(); } @Override public void method() { before(); source.method(); atfer(); } private void atfer() { System.out.println("代理之后!"); } private void before() { System.out.println("代理之前!"); } }
package com.ceshi7; public class ProxyTest { public static void main(String[] args) { Sourceable source = new Proxy(); source.method(); } }
测试结果:
忽然发现该代理模式和之前的装饰器模式极其相似。
区别仅在于需要用到的装饰器模式调用时引入了一个对象,而代理模式并没有;
但是其中思想并不同,装饰器模式只是将引用的类进行装饰,也就是用来扩展;
而代理模式则是用来代理处理一些相关事物。
所以修改的话使用代理模式是对代理类进行修改。装饰器模式是对接口的实现进行扩展。
一个是修改,一个是增加。两者经常结合使用。
感觉是增加一个装饰类仿佛是增加一个代理类,可以这么理解。
代理模式的应用场景:
如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:
1、修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则,即闭包原则。
2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。
使用代理模式,可以将功能划分的更加清晰,有助于后期维护。
如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:
1、修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则,即闭包原则。
2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。
使用代理模式,可以将功能划分的更加清晰,有助于后期维护。
即我们需要修改时只要修改代理类就可以了。
以上仅是静态代理,如果是动态代理呢?
package com.ceshi7; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyTest1 { public static void main(String[] args) throws Throwable { Source target = new Source(); //传入目标对象 //目的:1.根据它实现的接口生成代理对象 2.代理对象调用目标对象方法 Sourceable sourceable = (Sourceable) getProxy(target); sourceable.method(); } private static Object getProxy(final Object target) throws Exception{ //参数1:随便找个类加载器给它, 参数2:目标对象实现的接口,让代理对象实现相同接口 Class proxyClazz = java.lang.reflect.Proxy.getProxyClass(target.getClass().getClassLoader(), target.getClass().getInterfaces()); Constructor constructor = proxyClazz.getConstructor(InvocationHandler.class); Object proxy = constructor.newInstance(new InvocationHandler(){ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(method.getName() + "方法开始执行"); Object result = method.invoke(target, args); System.out.println(result); System.out.println(method.getName() + "方法执行结束"); return result; } }); return proxy; } private static Object getProxy1(final Object target) throws Exception{ Object proxy = Proxy.newProxyInstance( target.getClass().getClassLoader(), //类加载器 target.getClass().getInterfaces(), //让代理对象和目标对象实现相同接口 new InvocationHandler() {//代理对象的方法最终都会被JVM导向它的invoke方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(method.getName() + "方法开始执行"); Object result = method.invoke(target, args); System.out.println(result); System.out.println(method.getName() + "方法执行结束"); return result; } }); return proxy; } }
动态的给已有的接口所有实现类添加一个打印日志。