代理模式的理解
**代理模式:指为目标对象提供一个代理对象,外部对目标对象的访问,通过代理委托进行已达到控制访问的目的。
自己的理解:代理类再次封装目标类,代理类依赖于目标类(即将目标对象作为代理类的一个成员对象),同样实现相同的接口,达到增强方法(增加额外的操作)或者控制访问的目的。
具体实现看下面:
静态代理**
实现如下:
package myInterfaces;
public interface Speakable {
public void speak( String message);
}
package myObject;
import myInterfaces.Speakable;
public class Dog implements Speakable {
@Override
public void speak(String message) {
System.out.println("旺旺:"+message);
}
}
package myObject;
import myInterfaces.Speakable;
public class Person implements Speakable {
@Override
public void speak(String message) {
System.out.println("Hello:"+message);
}
}
package myProxy;
import myInterfaces.Speakable;
import myObject.Dog;
public class DogProxy implements Speakable {
private Dog dog;
public DogProxy(Dog dog){
this.dog=dog;
}
@Override
public void speak(String message) {
this.dog.speak(message);
System.out.println("运行时间:"+System.currentTimeMillis());
}
}
package myProxy;
import myInterfaces.Speakable;
import myObject.Person;
public class PersonProxy implements Speakable {/************实现相同的接口**********/
private Person person;/******************,再次封装,将目标对象作为一个成员变量*********/
public PersonProxy(Person person){
this.person=person;
}
@Override
public void speak(String message) {
this.person.speak(message);
System.out.println("运行时间:"+System.currentTimeMillis());/****额外的操作,,,增强方法******/
}
}
项目结构:
从上图可以看出静态代理的优点:
1)实现简单
2)容易理解
缺点:
1)实现起来类太多了。要为专门一个目标类写一个代理类,如一个Dog目标类,要写DogProxy,Person目标类,要写一个PersonProxy,如果目标类太多的话,代理类也需要同样多的代理类。类的数量成倍增加。
2)拓展性太差,可维护性差。如果考虑要为Speakble接口增加一个方法。那所有的目标类,所有的实现类都必须要重新修改,拓展性差,可维护性差。
全部报红,即全部的目标类和代理类全部需要修改
动态代理
动态代理demo如下
目标接口
package myInterfaces;
//目标接口
public interface Speakable {
public String speak();
}
实现类1
package myObject;
import myInterfaces.Speakable;
//目标类
public class Dog implements Speakable {
@Override
public String speak() {
return "旺旺";
}
}
实现类2
package myObject;
import myInterfaces.Speakable;
//目标类
public class Person implements Speakable {
@Override
public String speak() {
return "Hello";
}
}
调用处理器
package myhandler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//调用处理器
public class MyHandler implements InvocationHandler {//实现固定接口
Object target;//目标对象
public MyHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object res=null;
res=method.invoke(target, args);//调用目标方法
if(res!=null){
System.out.println("新年快乐 "+(String)res);//方法增强
}
return res;
}
}
main方法
package main;
import myInterfaces.Speakable;
import myObject.Dog;
import myObject.Person;
import myhandler.MyHandler;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) {
//目标对象
Speakable dogspeak=new Dog();
//传入调用处理器
InvocationHandler doghandler=new MyHandler(dogspeak);
//获取代理对象
Speakable dogproxy =(Speakable)Proxy.newProxyInstance(dogspeak.getClass().getClassLoader(),
dogspeak.getClass().getInterfaces(),
doghandler);
//调用方法
dogproxy.speak();
Speakable personspeak =new Person();
InvocationHandler personhandler=new MyHandler(personspeak);
Speakable personproxy=(Speakable) Proxy.newProxyInstance(personspeak.getClass().getClassLoader(),
personspeak.getClass().getInterfaces(),
personhandler);
personproxy.speak();
}
}
动态代理就是通过反射机制,让jdk动态生成代理对象,而不需要再像静态代理那样为每个目标对象写一个代理类。原先要在代理对象中写的方法,现在写到调用处理器中。
在debug模式下看一下执行过程,代理对象调用的方法,实际上是调用处理器中的invoke方法。
这里也可以看出调用处理器就是一个抽象的代理类。根据你在实现过程中传入的参数,就可以动态的生成一个你所需的代理类。
动态代理的实现步骤如下:
1.创建接口,定义目标类要完成的功能
2. 创建目标类实现接口
3. 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能 (增强功能,或方法)
4.使用Proxy类的静态方法,创建代理对象。 并把返回值转为接口类型。