Java中的***

当需要调用一个目标对象执行一个方法做某件事时,这时不方便直接用目标对象,或没有目标对象,则可以通过***对象间接的调用目标对象的方法。
***作用:对目标对象进行控制功能增强

静态***

静态***:***类是提前创建好的,只要直接通过***对象调用目标对象即可(静态***类似于装饰者模式,不过装饰者模式作用主要在于对 被装饰者的功能增强,而***作用主要在于对目标对象进行控制


Singer(歌手):***类与目标类共同实现的接口

//***对象需要有目标对象全部的方法,***对象与目标对象要实现共同的接口
public interface Singer {
    //唱歌
    void sing(String song);
    //跳舞
    void dance(String danceName);
}

ZhangSan(张三):目标类(被***的类)

//目标类
public class ZhangSan implements Singer {

    @Override
    public void sing(String song) {
        System.out.println("唱:"+song);
    }

    @Override
    public void dance(String danceName) {
        System.out.println("跳:"+danceName);
    }
}

Agent(经纪人):***对象类

//***对象
public class Agent implements Singer {
    private ZhangSan zhangSan;

    public Agent(ZhangSan zhangSan) {
        this.zhangSan = zhangSan;
    }

    @Override
    public void sing(String song) {
        //***对象要做的事情(体现了对目标对象的控制与功能增强):调用目标对象同名方法之前可做一些其他操作, 调用目标对象同名方法, 调用目标对象同名方法之后还再可做一些其他操作

        //调用目标对象同名方法之前做一些其他操作
        System.out.println("修改歌名");
        song="两只老虎";

        //调用目标对象同名方法
        zhangSan.sing(song);

        //调用目标对象同名方法之后还再可做一些其他操作
        System.out.println("唱完了");
    }

    @Override
    public void dance(String danceName) {
        System.out.println("跳:"+danceName);
    }

}

Test:测试运行

public class Test {
    public static void main(String[] arg){
        ZhangSan zhangSan = new ZhangSan();
        Agent agent = new Agent(zhangSan);
        agent.sing("怒放的生命");

    }
}

动态***

动态***:***类不存在,在代码运行过程中,动态生成的***类,再通过***类对象调用目标对象。

思考:生成***对象有什么要求?
***类应该与目标对象有相同方法—>需要提供***类要实现的接口
使用***是要对目标对象进行控制功能增强—>需要提供***类要做的事情
在代码运行过程中,动态生成的***类,加载到内存中,并创建***类对象—>需要提供类加载器

分两种情况:

  1. 有接口,有目标对象,生成***对象

Singer(接口)

//***对象需要有目标对象全部的方法,***对象与目标对象要实现共同的接口
public interface Singer {
    //唱歌
    void sing(String song);
    //跳舞
    void dance(String danceName);
}

Zhangsan(目标类)

//目标类
public class ZhangSan implements Singer {

    @Override
    public void sing(String song) {
        System.out.println("唱:"+song);
    }

    @Override
    public void dance(String danceName) {
        System.out.println("跳:"+danceName);
    }
}

Test(通过Proxy生成***对象,让***对象调用目标对象的方法)

public class Test {
    public static void main(String[] arg){
        //创建目标对象实例
        ZhangSan zhangSan = new ZhangSan();

        //通过Proxy生成***对象,让***对象调用目标对象的方法
            /*参数说明 loader :类加载器 interfaces :接口类的Class数组,表示需要给***的对象提供一组什么接口,提供接口后,***对象实现该接口,就能调用这组接口中的方法了。 InvocationHandler :指定***对象要做什么事情 singerProxy:生成的***对象 */
        Singer singerProxy = (Singer) Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{Singer.class}, new InvocationHandler() {

            //invoke方法,指定***对象的行为,返回执行结果
                /* proxy,***后的实例对象。 method,对象被调用方法。 args,调用时的参数。 */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //调用目标对象的方法之前,如果执行目标对象sing方法,更改参数值。
                if(method.getName().equals("sing")){
                    args[0]="凉凉";
                    System.out.println("换首凉凉,开始唱");
                }

                //反射调用目标对象的同名方法
                 /* 参数object:调用哪个对象的方法 参数parameterValues:调用方法时传递的实参 */

                Object invoke = method.invoke(zhangSan, args);

                //调用目标对象的方法之后
                System.out.println("表演完了");

                return invoke;
            }
        });

        //调用***对象方法
        singerProxy.sing("怒放的生命");
    }
}

  1. 有接口,没有目标对象,生成***对象

Singer(接口)

//***对象需要有目标对象全部的方法,***对象与目标对象要实现共同的接口
public interface Singer {
    //唱歌
    void sing(String song);
    //跳舞
    void dance(String danceName);
}

Test(通过Proxy生成***对象,由***对象完成所有工作)

public class Test {
    public static void main(String[] arg){
        //通过Proxy生成***对象,由***对象完成所有工作
            /*参数说明 loader :类加载器 interfaces :接口类的Class数组,表示需要给***的对象提供一组什么接口,提供接口后,***对象实现该接口,就能调用这组接口中的方法了。 InvocationHandler :指定***对象要做什么事情 singerProxy:生成的***对象 */
        Singer singerProxy = (Singer) Proxy.newProxyInstance(Test.class.getClassLoader(), new Class[]{Singer.class}, new InvocationHandler() {

            //invoke方法,指定***对象的行为,返回执行结果
                /* proxy,***后的实例对象。 method,对象被调用方法。 args,调用时的参数。 */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //调用目标对象的方法之前,如果执行目标对象sing方法,更改参数值。
                if(method.getName().equals("sing")){
                    System.out.println("唱:"+args[0]);
                }else if (method.getName().equals("dance")){
                    System.out.println("跳:"+args[0]);
                }
                return null;
            }
        });
        //调用***对象方法
        singerProxy.sing("怒放的生命");
        singerProxy.dance("卡路里");
    }
}