代理模式:
为其他对象提供一种代理以控制对这个对象的访问,代理对象起到了中介作用,可以去掉功能服务或者额外的服务。
以火车站买票为例子:
火车票代售处是火车站的代理,代售处可能不止可以卖火车票,还可以卖飞机票,但是不支持火车票退票功能,因此代售处起到了中介作用,
可以去掉功能服务或者额外的服务。
常见代理模式:远程代理,虚拟代理,保护代理,智能引用代理。
智能引用代理
两种实现方式:静态代理,动态代理。
静态代理:代理和被代理对象在代理之前是确定的。他们都实现相同的接口或者继承相同的抽象类。
静态代理分继承方式和聚合方式两种实现。

实例:
通过代理,实现汽车行驶的方法,同时记录汽车的行驶时间。
普通不使用设计模式实现方式:
第一步:行驶接口:
package com.Proxy;
public interface Moveable {
void move();
}
第二步:实现汽车类:汽车类中实现行驶方法,里面记录行驶时间。
package com.Proxy;
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)+"毫秒");
}
}
第三步:测试:
package com.Proxy;
public class Client {
/*
* 测试类
* */
public static void main(String[] args) {
Car car=new Car();
car.move();
}
}
运行结果:
汽车开始形式.... 汽车行驶中.... 汽车结束行驶...汽车形式时间:602毫秒
修改为静态代理:
第一种静态代理:以继承的方式代理:
Car类修改为只有行驶方式:
package com.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();
}
}
}
新建Car2类继承Car类,通过super.方法()方式调用父类的方法,实现静态代理。
同时在这个方法里面实现记录开车时间。
package com.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)+"毫秒");
}
}
测试:
package com.Proxy;
public class Client {
/*
* 测试类
* */
public static void main(String[] args) {
Moveable m=new Car2();
m.move();
}
}
效果:
汽车开始形式.... 汽车行驶中.... 汽车结束行驶...汽车形式时间:497毫秒
第二种静态代理:以聚合的方式实现代理:
聚合的方式其实就是在一个类中调用另一个类的对象,一般在构造方法里面把另一个类的对象传进来。
实现:
Car类和接口同上。
新建Car3继承接口,同时在构造方法里面把Car类对象传进来。
package com.Proxy;
/*
* 以聚合方式代理:一个类中调用另一个类的对象
* */
public class Car3 implements Moveable{
private Car car;
public Car3(Car car)
{
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)+"毫秒");
}
}
测试:
package com.Proxy;
public class Client {
/*
* 测试类
* */
public static void main(String[] args) {
// 不使用代理方式
// Car car=new Car();
// car.move();
// //以继承方式实现代理
// Moveable m=new Car2();
// m.move();
//以聚合方式实现代理
Car car=new Car();
Moveable m2=new Car3(car);
m2.move();
}
}
效果:
汽车开始形式.... 汽车行驶中.... 汽车结束行驶...汽车形式时间:200毫秒
继承方式和聚合方式两种比较:
如果此时代理类除了要实现汽车行驶方法,还可能需要实现其他功能的代理,比如权限管理,日志处理。

1,对于继承方式的代理来说:
如果我想先记录汽车行驶时间,在记录日志,需要新建一个代理类。
假如此时我又想先记录日志,再记录汽车行驶时间,此时又得新建一个代理类。

所以使用继承方式不合适。
2,使用聚合方式就没这个问题,代码验证:
这里要实现两种方式:即先记录时间,再记录日志;和先记录日志,再记录时间。
实现的方式就是,各个功能分别建立一个代理类,并且代理类的构造方法不仅能够传递被代理类(Car),也能能够把其他的代理类传递进来,
以此实现上述的两种不同的实现方式。
代码:
新建一个时间记录代理类:
为了可以让构造方法里面的参数既可以是被代理的Car类,也可以是代理类。
package com.Proxy;
//时间代理
public class CarTimeProxy implements Moveable{
private Moveable m;
public CarTimeProxy(Moveable m)
{
this.m=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.Proxy;
//日志代理
public class CarLogProxy implements Moveable{
private Moveable m;
public CarLogProxy(Moveable m)
{
this.m=m;
}
@Override
public void move()
{
System.out.println("日志开始....");
m.move();
System.out.println("日志结束....");
}
}
新建测试类:测试类分别通过两个代理类顺序不同,把相关代理类传递给另一个代理类调用:
package com.Proxy;
//聚合的代理模式,各个代理类直接可以互相传递,组合,
public class Clien2 {
public static void main(String[] args) {
Car car=new Car();
// //先记录日志,再记录时间
// CarTimeProxy ctp=new CarTimeProxy(car);
// CarLogProxy clp=new CarLogProxy(ctp);//把时间代理传进去,这时候日志代理类代理了时间代理类
// clp.move();
//先记录日志,再记录日志,只需要调整一下代理类的顺序
CarLogProxy clp2=new CarLogProxy(car);
CarTimeProxy ctp2=new CarTimeProxy(clp2);//把时间代理传进去,这时候日志代理类代理了时间代理类
ctp2.move();
}
}
来源:https://www.cnblogs.com/alsf/p/8506866.html