代理模式的理解:就是指某个类(被代理类)可以有很多的方法(理解为可以通过这些方法实现某个功能),然后就是在这些方法中很多的方法都是重复的,只有部分方法是需要改变的(必须按某种顺序才能实现某个功能,大部分为流程重复,只有少部分核心方法需要修改),这时就可以创建一个代理类,将所有的重复流程全部在代理类中完成,而被代理类就只是需要完成它自己的核心业务就可以了;
//定义一个接口;
public interface ProxyClass {
//一个找房子的方法;
void find();
//一个签合同的方法;
void signContract();
}
第二步:创建一个实体类(被代理类)
//创建一个客户类作为被代理类
public class Client implements ProxyClass{
//这里都是用户也可以执行的方法;
@Override
public void find() {
System.out.println("用户自己寻找房子");
}
@Override
public void signContract() {
System.out.println("用户自己签合同");
}
}
第三步:创建一个代理类
//创建一个类似中介的类(代理类),这个类要实现代理接口
public class Intermediary implements ProxyClass{
//由于需要用到被代理类中的方法,自然就需要被代理类的对象
private ProxyClass proxyClass;
//通过构造方法的形式将被代理类对象传进来
public Intermediary(ProxyClass proxyClass) {
this.proxyClass = proxyClass;
}
@Override
public void find() {
System.out.println("由中介找房");
}
/*这个方法是代理类特有的方法,也就是说,其实代理类除了拥有和被代理类
一样的方法,也会拥有它自己的方法;
*/
public void compare() {
System.out.println("由中介比较");
}
@Override
public void signContract() {
//这里就可以调用被代理类中的同名核心方法了;
proxyClass.signContract();
}
}
测试类:
class Test{
public static void main(String[] args) {
Intermediary intermediary = new Intermediary(new Client());
intermediary.find();
intermediary.compare();
intermediary.signContract();
}
}
还是使用静态代理的例子,只是稍加修改;虽然有些步骤重复,但是为了接下来更方便了解,还是重新添加一遍;
第一步:先创建一个接口(含有两个实现类共有的抽象方法)
//定义一个接口;
public interface ProxyClass {
//一个找房子的方法;
void find();
//一个签合同的方法;
void signContract();
}
第二步:创建一个实体类(被代理类)
//创建一个客户类作为被代理类
public class Client implements ProxyClass{
//这里都是用户也可以执行的方法;
@Override
public void find() {
System.out.println("用户自己寻找房子");
}
@Override
public void signContract() {
System.out.println("用户自己签合同");
}
}
** 第三步:不再是创建一个静态的代理类**
//创建一个类,用于动态处理被代理类;
public class ClientHandler implements InvocationHandler{
// 首先这个类中,肯定是和我们的被代理类相关,因为需要调用被代理类中的方法;
private ProxyClass proxyClass;//用多态放置对象;
//创建一个构造方法,将上面的对象传进来;
public ClientHandler(ProxyClass proxyClass) {
this.proxyClass = proxyClass;
}
// 在这个类中可以创建一些类似于代理类的方法;
public void compare() {
System.out.println("由中介比较");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(proxyClass, args);//使用上面传进来的真实类对象即可调用其中的方法;
return null;
}
}
测试类:需要注意的方法是,Proxy.newProxyInstance(当前类的加载,真实类的实现接口,实现接口InvocationHandler的类的对象)
class Test{
public static void main(String[] args) {
//定义一个被代理类的对象;
Client client = new Client();
ClientHandler handler = new ClientHandler(client);
ProxyClass procyclient = (ProxyClass) Proxy.newProxyInstance(Test.class.getClassLoader(), client.getClass().getInterfaces(), handler);
procyclient.find();
handler.compare();//一样可以在这个类中创建一些可能被代理类不存在的操作;
procyclient.signContract();//调用被代理类的方法;
}
}
测试结果:
从上面的测试结果可以知道这个动态代理类一样可以创建代理类里面需要的方法,在我看来,动态代理的最大优势就是可以代理不同的真实类;比如:有一个实现了Star接口的真实类realStar类,那么只需要在Test的时候修改一下真实类的实现参数接口,就可以了,万一又忘了就照这个模式实践;