代理模式属于结构型模式,和装饰器模式很像,都可以为对象进行功能扩展,对装饰器模式来说,装饰者和被装饰者都实现同一个接口,对代理模式来说,代理类和被代理类都实现同一个接口。但两者侧重点不同,装饰器模式关注于在一个对象上动态的添加方法,而代理模式关注于控制对对象的访问。用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例,而当使用装饰器模式的时候,通常的做法是将原始对象作为一个参数传给装饰者的构造器。
interface BuyHouse{
void buyHouse();
}
class BuyHouseImp implements BuyHouse{
@Override
public void buyHouse() {
System.out.println("买房");
}
}
1.静态代理
/*
* 优点:可以做到在符合开闭原则的情况下对目标对象进行功能扩展。
* 缺点:1.每一个服务都得创建代理类,买房一个,买车一个等等。工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。
* 2.代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
*/
class ProxyBuyHouse implements BuyHouse{
BuyHouse instance;
public ProxyBuyHouse() {
instance = new BuyHouseImp(); //这里和装饰器模式不同
}
@Override
public void buyHouse() {
System.out.println("借钱");
instance.buyHouse();
System.out.println("装修");
}
}
public class StaticProxyModel {
public static void main(String[] args) {
BuyHouse buyer = new ProxyBuyHouse();
buyer.buyHouse();
}
}
2.动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/*
* 动态代理只是对类做了进一步抽象和封装,使其复用性和易用性得到进一步提升
* 动态代理类只能代理接口(不支持抽象类),代理类都需要实现InvocationHandler类,实现invoke方法。该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法返回的值是被代理接口的一个实现类。
* 动态代理与静态代理相比较,最大的好处就是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,可以灵活处理。
*/
public class DynamicProxyModel {
public static void main(String[] args) {
BuyHouse buyHouse = new BuyHouseImp();
BuyHouse buyer = (BuyHouse)Proxy.newProxyInstance(buyHouse.getClass().getClassLoader(), buyHouse.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("借钱");
Object result = method.invoke(buyHouse, args);
System.out.println("装修");
return result;
}
});
buyer.buyHouse();//执行目标的方法会自动触发处理器的invoke方法
}
}