在有些情况下,一个客户不能或者不想直接访问另一个对象,这时需要找一个中介帮忙完成某项任务,这个中介就是代理对象。例如,购买火车票不一定要去火车站买,可以通过 12306 网站或者去火车票代售点买。又如找女朋友、找保姆、找工作等都可以通过找中介完成。
什么情况下使用代理?
设计模式中有一个设计原则是开闭原则,是说对修改关闭对扩展开放,我们在工作中有时会接手很多前人的代码,里面代码逻辑让人摸不着头脑,这时就很难去下手修改代码,那么这时我们就可以通过代理对类进行增强。
我们在使用RPC框架的时候,框架本身并不能提前知道各个业务方要调用哪些接口的哪些方法 。那么这个时候,就可用通过动态代理的方式来建立一个中间人给客户端使用,也方便框架进行搭建逻辑,某种程度上也是客户端代码和框架松耦合的一种表现。
Spring的AOP机制就是采用动态代理的机制来实现切面编程。
其主要缺点是:
在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
增加了系统的复杂度;
代理模式的与特点
1. 用户只关心接口功能,而不在乎谁提供了功能。
2. 接口真正实现者是 RealSubject,但是它不与用户直接接触,而是通过代理。
3. 代理就是Proxy,由于它实现了 Subject 接口,所以它能够直接与用户接触。
4. 用户调用 Proxy 的时候,Proxy 内部调用了 RealSubject。所以,Proxy 是中介者,它可以增强 RealSubject 操作
在Java中有两种代理模式,分为静态代理和动态代理,其中动态代理又分为JDK动态代理和Cglib动态代理
1.静态代理
我们平常去电影院看电影的时候,在电影开始的阶段是不是经常会放广告呢?
电影是电影公司委托给影院进行播放的,但是影院可以在播放电影的时候,产生一些自己的经济收益,比如卖爆米花、可乐等,然后在影片开始结束时播放一些广告。
现在用代码来进行模拟。
①.首先得有一个接口,通用的接口是代理模式实现的基础。这个接口我们命名为 IMovie。
public interface IMovie {
public void play();
public void stop();
public void over();
}
②.创建被代理的实体类
public class Movie implements IMovie{
@Override
public void play() {
System.out.println("电影开始~");
}
@Override
public void stop() {
System.out.println("电影暂停");
}
@Override
public void over() {
System.out.println("电影结束");
}
}
③.创建代理对象
public class MovieProxy implements IMovie{
public IMovieiMovie;
public MovieProxy(IMovie iMovie){
this.iMovie = iMovie;
}
@Override
public void play() {
System.out.println("电影就要开始啦,爆米花10元一包~");
iMovie.play();
}
@Override
public void stop() {
iMovie.stop();
}
@Override
public void over() {
iMovie.over();
System.out.println("电影结束了,请有秩序离场");
}
}
④.创建客户端
public class Client {
public static void main(String[] args) {
Movie movie =new Movie();
MovieProxy movieProxy =new MovieProxy(movie);
movieProxy.play();
movieProxy.over();
}
}
2.动态代理
代理对象,不需要实现接口
代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象
①.创建接口
public interface IFood {
void createFood(String foodName);
void eatFood(String foodName);
}
②.创建被代理类
public class Foodimplements IFood {
@Override
public void createFood(String foodName) {
System.out.println("正在烧制"+foodName);
}
@Override
public void eatFood(String foodName) {
System.out.println("正在吃"+foodName);
}
}
③.创建代理对象
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
Object food =new Food();
FoodHandler foodHandler =new FoodHandler(food);
IFood iFood = (IFood) Proxy.newProxyInstance
(food.getClass().getClassLoader(),food.getClass().getInterfaces(),foodHandler);
}
}