代理模式(Proxy Pattern)是结构型模式(Strutural)的一种,结构型模式模式描述如何将类或者对象结合在一起形成更大的结构。结构型模式的特点是通过组合类或者对象产生更大的结构以适应更高层次的逻辑需求。
代理模式的目的是:Provide a surrogate or placeholder for another object to control access to it.
意思是,为其他对象提供一种代理以控制这个对象的访问。
代理模式的UML类图如下所示:
它提供了3个角色:
抽象主题角色(Subject):它是真正主题角色和代理角色的共同的接口。
真正主题角色(RealSubject):它是业务逻辑的真正具体实现者,也被称为被委托角色。
代理主题角色(Proxy):也被称为代理类或者委托类,负责控制真正主题角色(RealSubject)的引用,负责在需要的时候创建或者删除真正主题对象,并且可以在真正主题对象逻辑执行的前后加上自己的代理逻辑。
下面就以租房子为例,讲述代理模式
package test;
public class RentHouse {
public void rent(String name) {
System.out.println("Renting :租了一个 "+name);
}
}
这个模拟很简单,但是现实中显然不是这么简单,租房子前要先去寻找房源,约谈房主。租完房子又要签订合同、搬家,这样这个租房子的流程才能结束。
package test;
public class RentHouse {
public void rent(String name) {
before();
System.out.println("Renting :租了一个 "+name);
after();
}
public static void before() {
System.out.println("--------寻找资源--------");
}
public static void after() {
System.out.println("--------签订合同--------------");
}
}
似乎还行,但是接下来可能我们还要去租汽车、租游艇、甚至租一个女友回家过年,都要在租之前寻找资源,租后签订合同,如果继续像这样会做很多重复的工作,并且每次都是自己身体力行,未免伤身,而且对于寻找资源和签订合同,我们自己去做不一定合适,极容易犯错。
于是乎,我们想到了中介,如果我们只需要付钱请中介,然后告诉他你需要什么,由中介帮助你去寻找资源,签订合同,这样就显得非常的轻松,而且不管租什么,都可以由中介帮助我们去完成,那么这个中介的角色就是一个代理角色。
因为要租非常多的东西,所以我们抽象出一个租赁接口Rent(p_name)作为抽象角色
package test.staticproxy;
public interface Rent {
//p_name:商品名称
public void rent(String p_name);
}
package test.staticproxy;
public class Renter implements Rent {
private String name;
public Renter(String name) {
this.name = name;
}
@Override
public void rent(String p_name) {
System.out.println("我是【"+name+"】,我要租【"+p_name+"】");
}
}
package test.staticproxy;
public class RentProxy implements Rent {
private Rent rent = null;
public Rent getRent() {
return rent;
}
public void setRent(Rent rent) {
this.rent = rent;
}
@Override
public void rent(String p_name) {
before();
rent.rent(p_name);
after();
}
public static void before() {
System.out.println("--------寻找资源--------");
}
public static void after() {
System.out.println("--------签订合同--------------");
}
}
package test.staticproxy;
public class Test {
public static void main(String[] args) {
RentProxy rentProxy = new RentProxy(); //中介,代理类
Rent renterA = new Renter("Tom"); //客户A,具体角色
Rent renterB = new Renter("Linda"); //客户B,具体角色
rentProxy.setRent(renterA);
rentProxy.rent("房子");
rentProxy.setRent(renterB);
rentProxy.rent("女友");
}
}
--------寻找资源--------
我是【Tom】,我要租【房子】
--------签订合同--------------
--------寻找资源--------
我是【Linda】,我要租【女友】
--------签订合同--------------
代理模式优点:
职责清晰:真正主题角色只需要专注于自己的业务逻辑,其它事务完全可以通过代理角色后期的代理完成。
高扩展性:具体主题角色可以有多个,代理角色可以代理多个具体的主题角色,因为它们都实现了同一个抽象角色的接口。
代理类完全可以在运行的时候才确定要真正代理的对象,这也就是真正的动态代理,那么通过手工加入或者工具加入的方式就是静态代理。