代理模式是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
比如买火车票,你一般不直接去火车站购买,而是到附近的售票点。售票点其实就是代理。
静态代理
要实现的接口
public interface Moveable {
void move();
}
package com.imooc.proxy;
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();
}
}
}
集成方式
package com.imooc.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) + "毫秒!");
}
}
集成方式就是直接继承父类,在super.move()加上自己所代理的内容,比如日志等等
聚合方式
package com.imooc.proxy;
public class Car3 implements Moveable {
public Car3(Car 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) + "毫秒!");
}
}
聚合不是继承而是实现,把car对象做为构造方法的传递对象。之后再调用car的move方法。
两种方法的对比
在集成方式中如果你要再加入日志的功能怎么办?
只能改原来的代码。如
package com.imooc.proxy;
public class Car2 extends Car {
@Override
public void move() {
System.out.println("打印日志")
long starttime = System.currentTimeMillis();
System.out.println("汽车开始行驶....");
super.move();
long endtime = System.currentTimeMillis();
System.out.println("汽车结束行驶.... 汽车行驶时间:"
+ (endtime - starttime) + "毫秒!");
}
}
在最前面加
但是如果是聚合模式呢?
只实现日志功能
package com.imooc.proxy;
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("日志结束....");
}
}
只实现计算时间功能
package com.imooc.proxy;
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) + "毫秒!");
}
}
package com.imooc.proxy;
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();
}
}
这样看,可能一开始看不懂
Car car = new Car();
CarLogProxy clp = new CarLogProxy(car);
CarTimeProxy ctp = new CarTimeProxy(clp);
ctp.move();
从后看
ctp.move();进入 ctp中的move
@Override
public void move() {
long starttime = System.currentTimeMillis();
System.out.println("汽车开始行驶....");
m.move();
long endtime = System.currentTimeMillis();
System.out.println("汽车结束行驶.... 汽车行驶时间:"
+ (endtime - starttime) + "毫秒!");
}
但是执行到 m.move(); 会去执行 clp的move
public void move() {
System.out.println("日志开始....");
m.move();
System.out.println("日志结束....");
}
执行到 m.move(); 会去执行car中的move
@Override
public void move() {
//实现开车
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶中....");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
之后是clp中的
System.out.println("日志结束....");
最后是
long endtime = System.currentTimeMillis();
System.out.println("汽车结束行驶.... 汽车行驶时间:"
+ (endtime - starttime) + "毫秒!");
可见!
聚合方式对代码的维护性更高,如果我要换计算时间和打印日志的位置,只要
Car car = new Car();
CarTimeProxy ctp = new CarTimeProxy(car);
CarLogProxy clp = new CarLogProxy( ctp);
clp.move();
把他们调换就可以了