1.代理设计模式的概念
在日常生活中,会遇到各种各样的中介机构,比如猎头公司、律师事务所、婚姻介绍所和房产公司等。在这些单位工作的人员均可以称为代理人。
代理人的共同特征是可以代替委托人去和第三方通信。例如,律师代替委托人打官司,猎头代替委托人去物色人才。代理人可以在第三方和委托人之间转发或过滤信息,但是不能取代委托人的任务。例如,房屋租赁人缴纳租金,房产经纪人不会把它私吞;一个男应征者要求与一个女应征者约会,红娘本身不会参与约会,只会通知双方约会。
代理模式也可以运用到面向对象的软件开发领域,它的特征是:代理类和委托类有相同的接口。代理类主要负责为委托类预处理消息、过滤信息以及把消息转发给委托方等,代理类和委托类之间为组合关系。
简单来说,代理设计模式就是为委托人提供一种代理来控制对委托人的访问。
结构:
2.代理设计模式的优缺点
优点:
1)职责清晰。委托人(被代理对象)只需要关注自己的业务逻辑,不用关心与其它模块或者调用者的交互。具体交互由代理对象(代理人)实现。
2)降低系统耦合,符合OCP原则。代理对象在客户端和目标对象之间起到中介的作用,可以保护目标对象(委托人)。
3)高扩展性。
缺点:
1)增加复杂度。
2)可靠性可能降低。代理对象可能在代理的时候增加一些“暗箱操作”,如房屋中中介从中抽取一部分提成。这就需要代理对象公开透明它的操作。
3.代理设计模式的应用场景
1)远程代理。 为一个对象在不同的地址空间提供局部代表,这样就可以隐藏一个对象存在于不同地址空间的事实。
2)虚拟代理。 根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象。
3)安全代理。 用来控制真实对象访问时的权限。
4)智能指引。 当调用真实对象时,代理类处理一些另外的事情。
4.静态代理模式与动态代理模式
静态代理模式:代理对象由程序员创建,一般一个代理类只能代表一类目标对象。静态代理需要代理类与目标类有一样的继承父类和实现接口。
动态代理模式:动态代理,也叫做JDK代理或接口代理。分为基于接口和抽象类。如果是基于接口,那么代理被必须实现InvocationHandler接口。如果是类,则需要利用第三方库cglib库实现。
动态代理:一个代理类代理所有类似接口。
静态代理模式:
package com.company.designPattern.proxy;
interface ISubject{
void buyCar();
}
//真实业务类
class RealSubject implements ISubject{
@Override
public void buyCar() {
System.out.println("买车");
}
}
//代理业务类
class ProxySubject implements ISubject{
private ISubject iSubject;//真正操作业务场景
public ProxySubject(ISubject iSubject) {
this.iSubject = iSubject;
}
@Override
public void buyCar(){
this.produceCar();
this.iSubject.buyCar();//调用真实业务
this.afterSale();
}
private void produceCar(){
System.out.println("生产宝马车");
}
private void afterSale(){
System.out.println("车的售后管理团队");
}
}
class Factory{
public static ISubject getInstance(){
return new ProxySubject(new RealSubject());//调用代理业务,传入真实业务需求
}
}
public class ProxyMethod {
public static void main(String[] args) {
ISubject subject=Factory.getInstance();
subject.buyCar();
}
}
结果:
动态代理示例:
package com.company.designPattern.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface ISubject{
void buyCar(int count);
}
//真实业务类
class RealSubject implements ISubject{
@Override
public void buyCar(int count) {
System.out.println("买"+count+"辆车");
}
}
//代理业务类
class ProxySubject implements InvocationHandler {
private Object realObject;//真正操作业务场景
/**
* 绑定真实主题类
* @param realObject
* @return 代理类
*/
public Object bind(Object realObject) {
this.realObject=realObject;
// public static Object newProxyInstance(ClassLoader loader,
// Class<?>[] interfaces,
// InvocationHandler h)
// throws IllegalArgumentException
return Proxy.newProxyInstance(realObject.getClass().getClassLoader(),
realObject.getClass().getInterfaces(),this);
}
private void produceCar(){
System.out.println("生产宝马车");
}
private void afterSale(){
System.out.println("车的售后管理团队");
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
this.produceCar();
//通过反射调用真实主题类方法
Object result=method.invoke(realObject,args);
this.afterSale();
return result;
}
}
public class ProxyMethod {
public static void main(String[] args) {
ISubject subject= (ISubject) new ProxySubject().bind(new RealSubject());
subject.buyCar(3);
}
}
结果:
注意:方法传参为
Proxy.newProxyInstance(真实业务类的类加载器,真实业务类的接口,实现了InvocationHandler的类对象)