一、代理模式简介
代理模式
为其他对象提供一种代理以控制对这个对象的访问。代理对象起到中介作用,可去掉功能服务或增加额外的服务。
代理模式分类
远程代理:为不同地理的对象提供局域网代表对象
虚拟代理:根据需要将资源消耗很大的对象进行延迟在真正需要的时候进行创建
保护代理:控制用户的访问权限
智能引用代理:提供对目标对象的额外服务
本文中将详细介绍智能引用代理,在智能引用代理中又细分为两个大类:静态代理和动态代理
二、静态代理模式
代理和被代理对象在代理之前是确定的,他们都实现相同的接口或继承相同的抽象类,通常静态代理的实现方式有两种
继承方式实现静态代理、聚合方式实现静态代理。下面通过一个实例来说明静态代理模式
假设有一个类Car实现了Moveable接口,其中有方法Move()表示汽车在移动中,这时我们需要记录汽车的行驶时间,通俗情况下的实现方法
Moveable.java
package com.study.proxy;
public interface Moveable {
void move();
}
Car.java
package com.study.proxy;
import java.util.Random;
public class Car implements Moveable {
@Override
public void move() {
try { //模拟汽车运行
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Car1.java
package com.study.proxy;
import java.util.Random;
public class Car implements Moveable {
//这种实现方式是对Car类进行了直接修改
@Override
public void move() {
long starttime = System.currentTimeMillis();
System.out.println("小汽车开始行驶");
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
long endtime = System.currentTimeMillis();
System.out.println("汽车行驶结束,行驶时间为:"+(endtime-starttime));
}
}
使用继承方式实现静态代理
Car2.java
package com.study.proxy;
public class Car2 extends Car {
@Override
public void move() {
long starttime = System.currentTimeMillis();
System.out.println("小汽车开始行驶");
super.move();
long endtime = System.currentTimeMillis();
System.out.println("汽车行驶结束,行驶时间为:"+(endtime-starttime));
}
}
使用聚合方式实现静态代理
Car3.java
package com.study.proxy;
public class Car3 implements Moveable {
public Car3(Car car) {
super();
this.car = car;
}
private Car car;
@Override
public void move() {
//代表被代理对象前处理逻辑
System.out.println("开动了");
car.move();
//代表被代理对象后处理逻辑
System.out.println("停止了");
}
}
思考一个问题:假如我们不仅需要先获得汽车的运行时间,还要后获得汽车运行的耗油量,那么继承方式的代理就需要重新编写代理类,如果要先获得汽车运行的耗油量后获得运行时间还要编写一个新的类,那么这种方式实现代理类的叠加会导致代理类不断地膨胀。而聚合方式每个类实现各自的代理功能,如果需要调配顺序则直接改变使用顺序就可以,相比而言更加灵活。所以,聚合方式比继承方式更适合实现静态代理。