面试题首页 > 设计模式面试题

代理模式面试题

001什么是代理模式?

给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用。其中代理对象起到中介作用,用于连接客户端和目标对象。例如:电脑桌面的快捷方式。电脑对某个程序提供一个快捷方式(代理对象),快捷方式连接客户端和程序,客户端通过操作快捷方式就可以操作那个程序。
通过引入代理对象的方式来间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性。

002代理模式的具体实现?

步骤1: 创建抽象对象接口(Subject):声明你(真实对象)需要让代购(代理对象)帮忙做的事(买Mac)

public interface Subject {  
    public void buyMac();
}

步骤2: 创建真实对象类(RealSubject),即”我“

public class RealSubject implement Subject{
   @Override
   public void buyMac() {  
       System.out.println(”买一台Mac“);  
   }  
}

步骤3:创建代理对象类(Proxy),即”代购“,并通过代理类创建真实对象实例并访问其方法

public class Proxy  implements Subject{
  
   @Override
   public void buyMac{   
     //引用并创建真实对象实例,即”我“
     RealSubject realSubject = new RealSubject();
     //调用真实对象的方法,进行代理购买Mac
     realSubject.buyMac();
     //代理对象额外做的操作
     this.WrapMac();
   }
   public void WrapMac(){
     System.out.println(”用盒子包装好Mac“);  
   }
}

步骤4:客户端调用

public class ProxyPattern {
    public static void main(String[] args){
    Subject proxy = new Proxy();
      proxy.buyMac();
    }      
}

结果输出
买一台Mac
用盒子包装好Mac

003代理模式的优缺点?

优点
协调调用者和被调用者,降低了系统的耦合度
代理对象作为客户端和目标对象之间的中介,起到了保护目标对象的作用
缺点
由于在客户端和真实主题之间增加了代理对象,因此会造成请求的处理速度变慢;
实现代理模式需要额外的工作(有些代理模式的实现非常复杂),从而增加了系统实现的复杂度。

004代理模式应用场景?

005为什么要使用动态代理?

在静态代理模式中一个静态代理只服务一种类型的目标对象,若要服务多类型的目标对象,则需要为每种目标对象都实现一个静态代理对象。在目标对象较多的情况下,若采用静态代理,则会出现 静态代理对象量多、代码量大,从而导致代码复杂的问题。

006什么是动态代理?

动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。在生成代理对象的过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法。可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作。
代理类在程序运行期间,创建的代理对象称之为动态代理对象。这种情况下,创建的代理对象,并不是事先在Java代码中定义好的。而是在运行期间,根据我们在动态代理对象中的“指示”,动态生成的。也就是说,你想获取哪个对象的代理,动态代理就会为你动态的生成这个对象的代理对象。动态代理可以对被代理对象的方法进行功能增强。有了动态代理的技术,那么就可以在不修改方法源码的情况下,增强被代理对象的方法的功能,在方法执行前后做任何你想做的事情。

007动态代理模式的原理?

1)动态代理不需要显式实现与目标对象类(RealSubject)相同的接口,而是将这种实现推迟到程序运行时由 JVM来实现。即:在使用时再创建动态代理类 & 实例;
2)通过Java 反射机制的method.invoke(),通过调用动态代理类对象方法,从而自动调用目标对象的方法。

008动态代理的优点和缺点?

优点
1)只需要1个动态代理类就可以解决创建多个静态代理的问题,避免重复、多余代码;
2)更强的灵活性;
缺点
1)效率低:相比静态代理中直接调用目标对象方法,动态代理则需要先通过Java反射机制 从而间接调用目标对象方法。
2)应用场景局限:Java 的单继承特性(每个代理类都继承了 Proxy 类),即只能针对接口创建代理类,不能针对类创建代理类。

009动态代理的应用场景。

日志记录、性能统计、安全控制、异常处理等。

010动态代理与静态代理模式的区别?

011JDK动态代理的实现步骤?

1.创建接口,定义目标类需要完成的功能
2.创建目标类,实现接口。
3.创建InvocationHandler接口的实现类。在invoke方法中完成代理类的功能。
      目标方法的调用
      功能增强
4.使用Proxy类中静态方法Proxy.newProxyInstance完成代理类对象的创建,返回代理对象,并把返回值转为接口类型。

public class JDKDynamicProxy {
    public static void main(String[] args) {
        CAProxy caProxy = new CAProxy();
        IA instance = (IA) caProxy.getInstance(new CA());
        instance.say();
        instance.fly();
    }
}
interface IA{
    void say();
    void fly();
}
class CA implements IA{
    @Override
    public void say() {
        System.out.println("I am class CA");
    }
    @Override
    public void fly() {
        System.out.println("I can fly");
    }
}
class CAProxy implements InvocationHandler{
    private Object target;
    public Object getInstance(Object object){
        this.target = object;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("I am proxy!");
        Object result = method.invoke(target, args);
        return result;
    }
}

012CGLib代理的实现步骤?

public class CglibDynamicProxy {
    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        A a = (A) cglibProxy.getInstance(new A());
        a.say();
    }
}
class A {
    public void say(){
        System.out.println("I am A");
    }
}
class CglibProxy implements MethodInterceptor{

    private Object target;
    public Object getInstance(Object object){
        this.target = object;
        Enhancer enhancer = new Enhancer();
        // 设置父类为实例类
        enhancer.setSuperclass(this.target.getClass());
        // 回调方法
        enhancer.setCallback(this);
        // 创建代理对象
        return enhancer.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("I am cglib proxy!");
        Object result = method.invoke(target, objects);
        return result;
    }
}

目录

返回顶部