主要讲智能引用代理
代理实现分为静态代理和动态代理。
静态代理
静态代理模式其实很常见,比如买火车票这件小事:黄牛相当于是火车站的代理,我们可以通过黄牛买票,但只能去火车站进行改签和退票。在代码实现中相当于为一个委托对象realSubject提供一个代理对象proxy,通过proxy可以调用realSubject的部分功能,并添加一些额外的业务处理,同时可以屏蔽realSubject中未开放的接口。
1、RealSubject 是委托类,Proxy 是代理类;
2、Subject 是委托类和代理类的接口;
3、request() 是委托类和代理类的共同方法;
2、Subject 是委托类和代理类的接口;
3、request() 是委托类和代理类的共同方法;
示例1:
抽象对象角色
public abstract class AbstractObject {
//操作
public abstract void operation();
}
目标对象角色
public class RealObject extends AbstractObject {
@Override
public void operation() {
//一些操作
System.out.println("一些操作");
}
}
代理对象角色
public class ProxyObject extends AbstractObject{
RealObject realObject = new RealObject(); //代理方法实际上是需要实际对象的
@Override
public void operation() {
//调用目标对象之前可以做相关操作
System.out.println("before");
realObject.operation();
//调用目标对象之后可以做相关操作
System.out.println("after");
}
}
客户端
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
AbstractObject obj = new ProxyObject();
obj.operation();
}
}
从上面的例子可以看出代理对象将客户端的调用委派给目标对象,在调用目标对象的方法之前跟之后都可以执行特定的操作。这个例子实际上是以下要将聚合的方式。
示例2:继承方式和聚合方式的对比
1.代理类继承实际类(委托类)
代理类和委托类的接口:
package proxy;
public interface Moveable {
void move();
}
委托类:import java.util.Random;
public class Car implements Moveable {
@Override
public void move() {
//实现开车
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶中....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
代理类:
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) + "毫秒!");
}
}
注:代理类继承了委托类,重写了委托类的方法。在重写时,可以直接调用委托类的方法,在之前和之后可以有自己的业务。
2.聚合的方式(代理类实际上是继承的公共来或实现的公共接口)
聚合指在一个类中调用另外一个类
此时的代理类:
public class Car3 implements Moveable {
public Car3(Car car) { //也可以像示例1一样new一个car
super();
this.car = car;
}
private Car car;
@Override
public void move() {
long starttime = System.currentTimeMillis();
System.out.println("汽车开始行驶....");
car.move();
long endtime = System.currentTimeMillis();
System.out.println("汽车结束行驶.... 汽车行驶时间:"
+ (endtime - starttime) + "毫秒!");
}
}
示例3:
实现类实现公共接口,其他的多个代理也实现这个公共接口。某个代理要调用实现类实例或另外的代理类实例,调用的参数也通过接口实现。这样有极大的扩展性。
公共接口:
public interface Moveable {
void move();
}
实现类:
public class Car implements Moveable {
@Override
public void move() {
//实现开车
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶中....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
代理之间只知道有实现类方法或代理类方法,具体顺序可以改变时,用如下代码可以实现:
代理1:(增加了时间)public class CarTimeProxy implements Moveable {
public CarTimeProxy(Moveable m) {
super();
this.m = m;
}
private Moveable m;
@Override
public void move() {
long starttime = System.currentTimeMillis();
System.out.println("汽车开始行驶....");
m.move();
long endtime = System.currentTimeMillis();
System.out.println("汽车结束行驶.... 汽车行驶时间:"
+ (endtime - starttime) + "毫秒!");
}
}
代理2:(增加了日志)
public class CarLogProxy implements Moveable {
public CarLogProxy(Moveable m) {
super();
this.m = m;
}
private Moveable m;
@Override
public void move() {
System.out.println("日志开始....");
m.move();
System.out.println("日志结束....");
}
}
实验:
public class Client {
/**
* 测试类
*/
public static void main(String[] args) {
Car car = new Car();
CarLogProxy clp = new CarLogProxy(car);
CarTimeProxy ctp = new CarTimeProxy(clp);
ctp.move();
}
}
//结果
汽车开始行驶....
日志开始....
汽车行驶中....
日志结束....
汽车结束行驶.... 汽车行驶时间:362毫秒!
-------------------------------------------------------------------
public class Client {
/**
* 测试类
*/
public static void main(String[] args) {
Car car = new Car();
CarTimeProxy ctp = new CarTimeProxy(car);
CarLogProxy clp = new CarLogProxy(ctp);
clp.move();
}
}
//结果
日志开始....
汽车开始行驶....
汽车行驶中....
汽车结束行驶.... 汽车行驶时间:662毫秒!
日志结束....
小结:示例3的结果表明,聚合的方式灵活
下一篇:动态代理