静态代理、装饰者模式和动态代理

本文详细介绍了Java中的静态代理、装饰者模式和动态代理,探讨了它们的目的、实现方式及区别。静态代理用于保护和隐藏目标对象,装饰者模式则用于功能增强。动态代理利用Java的Proxy类在运行时动态创建代理对象,无需预先编写代理类代码。通过这些代理模式,可以在不修改原有类的基础上扩展其功能。
摘要由CSDN通过智能技术生成

静态代理、装饰者模式和动态代理

为什么用代理?

有些类不能被修改的,因业务需要需要扩展这个类的功能。使用代理模式,可以基于被代理类不变的前提下,对被代理类的行为进行控制和扩展。

##静态代理
定义接口

//接口,规定了方法
public interface Car {
    public abstract void drive();
}

定义被代理类

import domain.Car;
/*
* 被代理类,实现接口
* */
public class Benchi implements Car {

    @Override
    public void drive() {
        System.out.println("启动速度快!");
    }
}

定义代理类

/*
* 代理类
* */
public class BenchiProxy implements Car {
    private Car benchi;

    //在无参构造器中,创建代理对象
    public BenchiProxy() {
        this.benchi = new Benchi();
    }

    @Override
    public void drive() {
        System.out.println("百公里加速5s");
        benchi.drive();
    }
}

调用

public class benchiTest {
    public static void main(String[] args) {
        BenchiProxy benchiProxy = new BenchiProxy();
        benchiProxy.drive();
    }
}

结果

百公里加速5s
启动速度快!

##装饰者模式
定义接口

//接口,规定了方法
public interface Car {
    public abstract void drive();

}

定义被装饰类

/*
 * 被装饰类,实现接口
 * */
public class Benchi implements Car {

    @Override
    public void drive() {
        System.out.println("启动速度快!");
    }
}

定义装饰类

/*
* 装饰类
* */
public class BenchiProxy implements Car {
    private Car benchi;

    //在有参构造器中,创建代理对象
    public BenchiProxy(Car benchi) {
        this.benchi = benchi;
    }

    @Override
    public void drive() {
        System.out.println("百公里加速5s");
        benchi.drive();
    }
}

调用

public class benchiTest {
    public static void main(String[] args) {
        Benchi benchi = new Benchi();
        BenchiProxy benchiProxy = new BenchiProxy(benchi);
        benchiProxy.drive();
    }
}

静态代理类和装饰者模式之间的共同点
1.都要实现与目标类相同的业务接口
2.在两个类中都要生命目标对象(被代理对象和被装饰对象)
3.都可以在不修改目标类的前提下增强方法
静态代理类和装饰者模式之间的不同点
1.目的不同:装饰者是为了增强目标对象;静态代理是侧重与保护和隐藏目标对象
2.对于目标对象的获取方式不同
装饰者中目标对象的获取,是通过有参构造器传入;静态代理中,是在无参构造器中之间创建,直接指定了不能改。
3.功能增强的实现这不同。
装饰者模式中存在装饰者基类,其并不能实现增强,而是由具体的装饰者进行增强的,所有其存在着“装饰者链”;
静态代理中,一般不存在父子类的关系,具体的增强就是有代理类实现的,无需其子类完成,所以不存在链的概念。

##动态代理
重点还是在与动态代理的应用和理解上,java为提供了Proxy类帮助实现动态代理,实现起来也很简单。不需要创建代理类,只需要已知被代理类和被代理类的实现接口。
给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用;被代理的对象难以直接获得或者是不想暴露给客户端。

  • 不需要在编译的时候把代理类写死,而是在运行时动态的的创建被代理类的代理对象
package com.atguigu.java;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//接口
interface Human{
    String getBelief();
    void eat(String food);

}
//被代理类
class SuperMan implements Human{

    @Override
    public String getBelief() {
        return "I believe I can fly!";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜欢吃" + food);
    }
}

class ProxyFactory{
    //使用此方法返回一个代理类对象
    public static Object getProxyInstance(Object obj){//代理对象
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
        myInvocationHandler.bind(obj);
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),myInvocationHandler);
    }
}
class MyInvocationHandler implements InvocationHandler{
    //当我们通过代理类的对象,调用方法a时,就会自动的调用如下方法invoke()
    //将被代理类要执行的方法a的功能就生命在invoke()中
    private Object obj;
    public void bind(Object obj){
        this.obj = obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
        Object returnValue = method.invoke(obj, args);
        return returnValue;
    }
}
public class ProxyTest {
    public static void main(String[] args)  {
        SuperMan superMan = new SuperMan();
        //代理类对象
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
        //调用代理类的方法时,内部调用被代理类的方法
        proxyInstance.getBelief();
        proxyInstance.eat("麻辣烫");
    }
}

其中

Proxy.newProxyInstance创建的是ITeacher 对象,其中的参数解释如下:

  • ClassLoader loader,类加载器。被代理类的类加载器。

  • Class<?>[] interfaces,被代理类所实现的接口,这个接口也可以是多个

  • InvocationHandler
    h,绑定代理类方法。代理类每调用一次任一方法,h(InvocationHandler)的invoke方法对应调用一次。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值