代理工厂模式(静态与动态代理)
代理工厂模式
1.静态代理工厂设计模式基础版
所谓代理模式,就是两个子类共同实现一个接口,其中一个子类负责真实业务实现,另外一个子类完成辅助真实业务主题的操作。
代理模式的核心就是代理类接收了真实类的一个对象,从而保证了核心业务的实现,然后再通过代理类的辅助方法完成对真实业务的修饰,然后再通过一个工厂类来产生我们需要的对象(工厂模式);
本篇文章主要讲述代理模式,但我在其中也加上了基础工厂(很简单);
package com.bitten.file.factory;/*** @Author : YangY* @Description :* @Time : Created in 11:50 2019/4/5*/
interface ISubject {void eat();
}
class RealSubject implements ISubject {@Overridepublic void eat() {System.out.println("吃饭饭!");}
}
class ProxySubject implements ISubject {//用来接收真实业务的对象ISubject subject;public ProxySubject(ISubject subject) {this.subject = subject;}public void beforeEat() {System.out.println("饭前打豆豆!");}public void afterEat() {System.out.println("饭后洗刷刷!");}@Overridepublic void eat() {beforeEat();this.subject.eat();afterEat();}
}
//工厂
class Factory {public static Object newInstance() {return new ProxySubject(new RealSubject());}
}
public class TestProxy {public static void main(String[] args) {ISubject sub = (ISubject) Factory.newInstance();sub.eat();}
}
2.静态代理用反射机制实现
下面的代理模式运用上了我们的反射,本质还是跟静态代理一样,只是变了变形式;
package www.bitten.java;import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;/*** @Author : YangY* @Description : 代理工厂与反射* @Time : Created in 18:31 2019/3/29*/interface ISubject {void eat();
}
//真实业务类
class RealSubject implements ISubject {@Overridepublic void eat() {System.out.println("核心业务:饿了吃饭");}
}
//代理类
class ProxySubject implements ISubject {private ISubject subject;public ProxySubject(ISubject subject) {this.subject = subject;}public void prepare() {System.out.println("辅助业务:饭前洗手");}public void afterEat() {System.out.println("辅助业务:洗碗");}@Overridepublic void eat() {this.prepare();subject.eat();this.afterEat();}
}
class Factory {private Factory() {}public static <T> T getInstance(String className) {T t = null;try {t = (T)Class.forName(className).newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return t;}/**** @param className* @param obj 要传入的是真实业务的对象* @param * @return*/ public static <T> T getInstance(String className,Object obj) {T t = null;try {try {Constructor cons = Class.forName(className).getConstructor(obj.getClass().getInterfaces()[0]);t = (T)cons.newInstance(obj);} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}} catch (NoSuchMethodException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return t;}
}public class Test2 {public static void main(String[] args) {ISubject subject = Factory.getInstance("www.bitten.java.ProxySubject",Factory.getInstance("www.bitten.java.RealSubject"));subject.eat();}
}
2.静态代理反射模式改进版
以上程序如果结合反射之后,整体的处理会非常繁琐。不光开发端,使用者使用起来也很麻烦。对于以上操作,客 户端最多只需要关系代理是谁,实际业务是谁即可。
所以我们在工厂类将实例化对象的方法参数设置为代理类和真实业务类的名称,客户端只需输入代理商和业务商名称即可完成。
下面代码为了看起来更简洁,没有像上面代码用try,catch块来捕获受查异常,而是直接在方法名上throws所有受查异常的父类Exception,效果都一样;
package www.bitten.java;import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;/*** @Author : YangY* @Description : 代理工厂与反射* @Time : Created in 18:31 2019/3/29*/interface ISubject {void eat();
}
class RealSubject implements ISubject {@Overridepublic void eat() {System.out.println("核心业务:饿了吃饭");}
}
class ProxySubject implements ISubject {private ISubject subject;public ProxySubject(ISubject subject) {this.subject = subject;}public void prepare() {System.out.println("辅助业务:饭前洗手");}public void afterEat() {System.out.println("辅助业务:洗碗");}@Overridepublic void eat() {this.prepare();subject.eat();this.afterEat();}
}
class Factory {private Factory() {}public static <T> T getInstance(String className) throws Exception{T t = null;t = (T)Class.forName(className).newInstance();return t;}public static <T> T getInstance(String proxyClassName,String realClassName) throws Exception{T t = null;//通过本类方法获取真实业务类的对象T obj = getInstance(realClassName);Constructor cons = Class.forName(proxyClassName).getConstructor(obj.getClass().getInterfaces()[0]);t = (T)cons.newInstance(obj);return t;}
}public class Test2 {public static void main(String[] args) throws Exception{ISubject subject = Factory.getInstance("www.bitten.java.ProxySubject","www.bitten.java.RealSubject");subject.eat();}
}
2.动态代理
为什么要用动态代理呢?这是一个很关键的问题
我们回首一下静态代理模式,代理类实现了核心操作接口,所以代理类必须得把所有核心操作业务覆写一遍,我们的辅助业务一样时,而且核心操作接口中有大量方法时,我们得覆写每一个方法,而且每一个方法中的辅助部分也一模一样,这样会重复许多代码;
要想进行动态代理设计的实现,代理类不再具体实现于某一个接口。(一般实现JDK自带的InvocationHandler接口) ,后面会介绍到,还有外部提供的动态代理接口;
package com.bitten.file;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** @Author : YangY* @Description :动态代理设计模式* @Time : Created in 16:31 2019/4/3*/
interface ISubject { //核心操作接口void eat(String msg,int num);
}class RealSubject implements ISubject {@Overridepublic void eat(String msg, int num) {System.out.println("我要吃"+num+"份"+msg);}
}class proxySubject implements InvocationHandler {//保存真实主题对象private Object target;/**** @param target* @return 返回动态代理对象*/public Object bind(Object target) {//保存真实主题对象this.target = target;//创建一个代理对象来代理真实需要代理的对象,代理对象的每个执行方法都会替换执行Invocation中的invoke方法return java.lang.reflect.Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}public void preHandle() {System.out.println("完成吃饭前业务");}public void afterHandle() {System.out.println("完成吃饭后业务");}/*** proxy:代表动态代理对象* method:代表正在执行的方法* args:代表调用目标方法时传入的实参*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//通过这来查看invoke方法调用了啥方法System.out.println("调用了"+method.getName()+"方法");this.preHandle();Object ret = method.invoke(target,args);this.afterHandle();return ret;}
}public class Proxy {public static void main(String[] args) {ISubject subject =(ISubject) new proxySubject().bind(new RealSubject());subject.eat("苹果",5);}
}//输出:
//调用了eat方法
//完成吃饭前业务
//我要吃5份苹果
//完成吃饭后业务
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
