代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
组成:
抽象角色:通过接口或抽象类声明真实角色实现的业务方法。 (以下例子中 :指接口 Courier)
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
(以下例子中指小李 )
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。 (以下例子中指小王)
情景模拟 : 小王和小李都刚成为了快递员,他们都可以完成 取货,送货的任务。(即真实角色和代理角色实现同一个接口),某日,小王取到1个货,发现货主是前不久和他争吵过的人名叫小八,所以小王不方便见到货主小八,这时,小王求助小李,让小李帮忙,但是他们每天一起取货,送货,小王知道小李也很忙,每天要送的东西很多。小王也不能全权将活都交给小李办,所以小王决定,取货,送货还是小王自己完成。只需要在最后一步,就是当面送给小八的时候,让小李代劳。这样,小八不知道是小王取货,送货的。他只看到了小李,没看到小王.....(小王和小八不能见面,否则就成了小王八,小王知道货主是小八,但是小八不能知道真实完成工作的是快递员小王) 以下为小王和小李都要实现的接口:
public interface Courier {
/**
* 送货员接口
* 2个方法: 1取货
* 2送货
*/
void getGoods() ;
void TransGoods();
}
以下为小王:
public class RealObject implements Courier{
Customer customer ;
public RealObject(Customer customer ) {
this.customer =customer ;
}
@Override
public void getGoods() {
System.out.println("我是小王,我取到了货,发现是"+customer.getName()+"的");
}
@Override
public void TransGoods() {
System.out.println("我是小王,我给"+customer.getName()+"送货了,但是最终不能由我本人当面给他");
}
}
注意在构造器中,我们将参数类型为Customer,此举为模拟小王知道货主是小八。
以下是小李,代理人:
public class ProxyObject implements Courier{
RealObject xiaowang ;
public ProxyObject(Customer customer) {
xiaowang = new RealObject(customer);
}
@Override
public void getGoods() {
xiaowang.getGoods();
}
@Override
public void TransGoods() {
xiaowang.TransGoods();
}
}
我们发现:在构造器中有真实对象的引用,即小王。而且实现了接口的2个方法,但是在里面,都是由小王做的。
以下为顾客类,只需要1个构造器和name属性,以及getter和setter
public class Customer {
private String name ;
public Customer() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
以下为测试类以及运行结果:
public class Test {
public static void main(String[] args){
Customer customer = new Customer();
customer.setName("小八");
ProxyObject xiaoli = new ProxyObject(customer);
xiaoli.getGoods();
xiaoli.TransGoods();
}
}
我是小王,我取到了货,发现是小八的
我是小王,我给小八送货了,但是最终不能由我本人当面给他
Process finished with exit code 0
在测试类中,我们new了一个代理对象,名叫小李。并且模拟小李见到了货主小八(即构造器里的参数 我们将name设置为小八),小八认为是小李完成了取货送货操作(但是从输出语句我们知道实际是小王完成的 )。 小李也没多说什么就走了。。。。小王最终达到了他的目标。
代理模式注意事项: 1、真实角色和代理角色都要实现同1个接口 使得在任何使用真实角色的地方可以用代理角色代替
2、代理类中,要保存1个真实角色的引用,使得代理可以访问到真实实体。
3、在代理类中,可以做很多附加操作(就比如,小李在给小八送货物途中可以对货进行修改)。
JavaEE的框架中,很多地方都用到了代理设计模式,如JDK动态代理以及cglib动态代理等,它们往往是为了增强真实类而存在的!
参考书籍 :《大话设计模式》