一、静态代理
代理和被代理对象在代理之前是确定的,他们都实现相同的接口或者继承相同的抽象类。UML模型如下: 6632620276117148876.jpg下面分别通过继承和聚合的方式实现静态代理。
二、继承方式实现静态代理
1、创建一个接口
public interface Moveable {
void move();
}
2、创建一个Car类
import java.util.Random;
public class Car implements Moveable {
@Override
public void move() {
long startTime=System.currentTimeMillis();
System.out.println("汽车开始行驶。。。");
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶中。。。");
} catch(InterruptedException e) {
e.printStackTrace();
}
long endTime=System.currentTimeMillis();
System.out.println("汽车结束行驶。。。行驶时间 " + (endTime - startTime) + " 秒");
}
}
3、通过继承的代理方式来实现记录汽车行驶时间,新建Car2类,继承Car类。此时注释掉Car类中的行驶起止时间。
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();
}
}
}
Car2类如下定义:
public class Car2 extends Car {
public Car2() {
super();
}
@Override
public void move() {
long startTime=System.currentTimeMillis();
System.out.println("汽车开始行驶。。。");
super.move();
long endTime=System.currentTimeMillis();
System.out.println("汽车结束行驶。。。行驶时间 " + (endTime - startTime) + " 秒");
}
}
测试类:
public class ProxyTest {
public static void main(String[] args) {
Moveable moveable=new Car2();
moveable.move();
}
}
输出结果:
汽车开始行驶。。。
汽车行驶中。。。
汽车结束行驶。。。行驶时间 968 秒
三、聚合方式实现静态代理
聚合概念:一个类中会调用另一个对象。
1、创建一个Car3类,实现Moveable接口。
public class Car3 implements Moveable {
private Car car;
public Car3(Car car) {
super();
this.car=car;
}
@Override
public void move() {
long startTime=System.currentTimeMillis();
System.out.println("汽车开始行驶。。。");
car.move();
long endTime=System.currentTimeMillis();
System.out.println("汽车结束行驶。。。行驶时间 " + (endTime - startTime) + " 秒");
}
}
2、测试类:
public class ProxyTest {
public static void main(String[] args) {
Car car=new Car();
Moveable moveable=new Car3(car);
moveable.move();
}
}
3、输出结果:
汽车开始行驶。。。
汽车行驶中。。。
汽车结束行驶。。。行驶时间 10 秒
四、继承方式实现代理的优缺点
如果要叠加业务,比如说要加权限的处理,加日志的处理。则需定义新的子类,继承Car2或者Car3,在move方法进行权限或日志的处理。根据叠加业务及处理顺序不同,分别要创建不同的子类,这样子类会无限膨胀下去,不好管理。但是聚合可以避免这个问题。
五、聚合的优势体现
需求:叠加对日志的处理及日志的处理
1、新建日志代理类,实现Moveable接口:
public class CarLogProxy implements Moveable {
private Moveable m;
public CarLogProxy(Moveable m) {
super();
this.m=m;
}
@Override
public void move() {
System.out.println("日志开始。。。");
m.move();
System.out.println("日志结束。。。");
}
}
2、新建时间代理类,实现Moveable接口:
public class CarTimeProxy implements Moveable {
private Moveable m;
public CarTimeProxy(Moveable m) {
super();
this.m=m;
}
@Override
public void move() {
System.out.println("汽车开始行驶。。。");
m.move();
System.out.println("汽车结束行驶。。。");
}
}
3、Car类
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();
}
}
}
4、测试类:
public class Test {
public static void main(String[] args) {
Car car=new Car();
CarLogProxy carLogProxy=new CarLogProxy(car);
CarTimeProxy carTimeProxy=new CarTimeProxy(carLogProxy);
carTimeProxy.move();
}
}
5、输出结果:
汽车开始行驶。。。
日志开始。。。
汽车行驶中。。。
日志结束。。。
汽车结束行驶。。。
6、改变代理顺序进行测试:
public class Test {
public static void main(String[] args) {
Car car=new Car();
CarTimeProxy carTimeProxy=new CarTimeProxy(car);
CarLogProxy carLogProxy=new CarLogProxy(carTimeProxy);
carLogProxy.move();
}
}
7、返回结果:
日志开始。。。
汽车开始行驶。。。
汽车行驶中。。。
汽车结束行驶。。。
日志结束。。。
很显然,聚合实现代理方式比继承代理方式更为灵活,代理之间可以互相组合,互相传递。
但是又问题来了,如果要实现火车,自行车对时间的代理呢,则又需要创建火车的时间代理类,自行车的时间代理类。火车的日志代理类,自行车的日志代理类,代理类仍然会膨胀下去。可以通过动态代理来解决这个问题。
网友评论