代理模式中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。
在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
优缺点优点:
- 被代理类可以更加专注于主要功能的实现,在一定程度上降低了系统的耦合度。
- 代理类可以提供额外的功能 。
缺点:
实现代理模式需要额外的工作,有些代理模式的实现非常复杂 。
使用场景- 在访问对象时附加一些 *** 作。
- 控制对原始对象的访问,比如过滤器。
分为静态代理和动态代理。
静态代理在使用静态代理时,需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者继承相同的父类。
接口
public interface IMovie {
void play();
}
实现类
public class Movie implements IMovie {
@Override
public void play() {
System.out.println("观看电影中~~~~~~");
}
}
代理类
public class MovieProxy implements IMovie {
Movie movie;
public MovieProxy(Movie movie) {
this.movie = movie;
}
@Override
public void play() {
System.out.println("电影马上开始了!");
movie.play();
System.out.println("电影已结束,请有序退场!");
}
}
这里也可以把增强代码封装成一个方法,再次解耦。
测试类
public class Main {
public static void main(String[] args) {
Movie movie = new Movie();
IMovie movieProxy = new MovieProxy(movie);
movieProxy.play();
}
}
--------结果------
电影马上开始了!
观看电影中~~~~~~
电影已结束,请有序退场!
这里能看出,静态代理需要绑每个实现类都创建一个接口和一个代理类,如果实现类极多的情况下,是十分不方便的事。
所以产生了动态代理,利用反射,让我们的增强代码和实现类真正的解耦。
动态代理分为JDK动态代理和CGLIB动态代理。这里使用JDK动态代理举例。
动态代理好处:
- 代理类不需要再实现接口了(实现类依旧需要)。
- 利用反射,动态在内存中构建代理对象。
JDK实现动态代理必须有实现 InvocationHandler 接口的处理类,如果需要写增强代码,则需重写 invoke 方法。
接口
public interface IMovie {
void play();
}
实现类
public class Movie implements IMovie {
@Override
public void play() {
System.out.println("观看电影中~~~~~~");
}
}
代理类
这里使用了Object修饰对象,能让我们这个代理类,代理不同的实现类。同时利用了反射来获取实现类需要实现的方法,不再指定某个方法了。这些方式让我们的动态代理真正的实现了解耦。
public class MovieProxy {
private Object target;
public MovieProxy(Object target) {
this.target = target;
}
public Object getProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JDK代理开始~~");
System.out.println("电影马上开始了!");
// 反射机制调用目标函数的方法
Object ret = method.invoke(target, args);
System.out.println("电影已结束,请有序退场!");
System.out.println("JDK代理结束~~");
return ret;
}
});
}
}
测试类
public class Main {
public static void main(String[] args) {
Movie target = new Movie();
IMovie proxyInstance = (IMovie) new MovieProxy(target).getProxyInstance();
proxyInstance.play();
}
}
--------结果------
JDK代理开始~~
电影马上开始了!
观看电影中~~~~~~
电影已结束,请有序退场!
JDK代理结束~~
PS:我们spring框架最重要之一的功能AOP就是使用了动态代理。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)