Java设计模式——代理模式

本文详细介绍了Java中的代理模式,包括静态代理和动态代理的实现方式。通过具体示例讲解了如何利用代理模式来扩展功能,并展示了如何在Android环境中实现动态代理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       java中的代理模式是一个很重要的模式很多地方都用到,比如Spring框架中。Android中也是比如adil中,比如现在非常流行的网络框架retrofit中等等很多地方都会用到。所以理解代理模式是非常重要的。今天就来谈一下代理模式。

    代理顾名思义就是代表另一个事物完成一些工作。也可以理解为中介。举个例子:链家买房子。大家都知道链家是卖房子的中介,它可以卖很多楼盘的房子。比如水岸连城和香格里两个小区。链家作为中介卖这两家的房子,买主不直接和房产商联系,通过链家来买房。

    下面我们先用代码来实现一个代理模式:

     首先 水岸连城和香格里两个小区嗾使楼盘,所以他们有一些共同的属性 来一个接口:

     

package com.chs.proxytext;

/**
 * 作者:chs on 2016/8/11 16:02
 * 邮箱:657083984@qq.com
 * 楼盘
 */
public interface LouPan {
    /**
     * 楼盘的名字
     */
    public void getName();

    /**
     * 楼的价格
     */
    public void getPrice();
}
    然后 水岸连城 和 香格里 分别 实现了这个接口

package com.chs.proxytext;

import android.util.Log;

/**
 * 作者:chs on 2016/8/11 16:07
 * 邮箱:657083984@qq.com
 * 水岸连城
 */
public class ShuiAn implements LouPan {
    @Override
    public void getName() {
        Log.i("name","水岸连城");
    }

    @Override
    public void getPrice() {
        Log.i("ShuiAn_price","5000");
    }
}

package com.chs.proxytext;

import android.util.Log;

/**
 * 作者:chs on 2016/8/11 16:08
 * 邮箱:657083984@qq.com
 * 香格里
 */
public class XiangGe implements LouPan {
    @Override
    public void getName() {
        Log.i("name","香格里");
    }

    @Override
    public void getPrice() {
        Log.i("XiangGe_price","3000");
    }
}

    然后是链家 链家的构造里面传入一个楼盘。也就是代理要持有被代理者的对象

package com.chs.proxytext;

import android.util.Log;

/**
 * 作者:chs on 2016/8/11 16:09
 * 邮箱:657083984@qq.com
 * 链家
 */
public class LianJIa implements LouPan {
    private LouPan louPan;

    public LianJIa(LouPan louPan) {
        this.louPan = louPan;
    }

    @Override
    public void getName() {
        louPan.getName();
    }

    @Override
    public void getPrice() {
        louPan.getPrice();
    }
}

      最后是main中:

package com.chs.proxytext;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        LianJIa lianJIa;

        ShuiAn shuiAn = new ShuiAn();
        lianJIa = new LianJIa(shuiAn);
        lianJIa.getName();
        lianJIa.getPrice();

        XiangGe xiangGe = new XiangGe();
        lianJIa = new LianJIa(xiangGe);
        lianJIa.getName();
        lianJIa.getPrice();
    }
}
 
    运行结果:

08-11 16:37:19.074 3558-3558/com.chs.proxytext I/name: 水岸连城
08-11 16:37:19.084 3558-3558/com.chs.proxytext I/ShuiAn_price: 5000
08-11 16:37:19.084 3558-3558/com.chs.proxytext I/name: 香格里
08-11 16:37:19.084 3558-3558/com.chs.proxytext I/XiangGe_price: 3000

    这样以后再有别的楼盘需要链家代理卖,就可以实现LouPan的接口后把自己给链家就可以了。

    java中也提供了动态代理的类供我们用,使用起来很简单,首先实现InvocationHandler.

    

package com.chs.proxytext;

import android.util.Log;

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

/**
 * 作者:chs on 2016/8/11 16:46
 * 邮箱:657083984@qq.com
 * 楼盘handler
 */
public class LouPanHandler implements InvocationHandler {
    /**
     * 这个就是我们要代理的真实对象
     */
    private Object subject;
    /**
     * 构造方法,给我们要代理的真实对象赋初值
     *
     * @param subject
     */
    public LouPanHandler(Object subject)
    {
        this.subject = subject;
    }

    /**
     *
     * @param proxy   代理类实例
     * @param method   被调用的方法对象
     * @param objects  调用参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] objects) throws Throwable {
        //在执行代理对象之前可以做一些别的事情
        Log.i("执行之前","执行之前做点事情");

        Object res = method.invoke(subject, objects);

        Log.i("执行之后","执行之后做点事情");
        return res;
    }
}
     main中:

package com.chs.proxytext;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

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

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        LianJIa lianJIa;

//        ShuiAn shuiAn = new ShuiAn();
//        lianJIa = new LianJIa(shuiAn);
//        lianJIa.getName();
//        lianJIa.getPrice();
//
//        XiangGe xiangGe = new XiangGe();
//        lianJIa = new LianJIa(xiangGe);
//        lianJIa.getName();
//        lianJIa.getPrice();
        LouPan louPanReal = new ShuiAn();
        InvocationHandler handler = new LouPanHandler(louPanReal);

        ClassLoader classLoader = louPanReal.getClass().getClassLoader();
        Class[] interfaces = louPanReal.getClass().getInterfaces();

        //获取代理的对象
        LouPan louPan = (LouPan) Proxy.newProxyInstance(classLoader,interfaces,handler);
        louPan.getName();
        louPan.getPrice();
    }
}

     这里我们将真实的对象传入handler 通过Proxy.newProxyInstance动态生成代理的对象。之后执行代理对象中的方法。

     执行结果:

08-11 17:47:30.364 31042-31042/com.chs.proxytext I/执行之前: 执行之前做点事情
08-11 17:47:30.364 31042-31042/com.chs.proxytext I/name: 水岸连城
08-11 17:47:30.364 31042-31042/com.chs.proxytext I/执行之后: 执行之后做点事情
08-11 17:47:30.364 31042-31042/com.chs.proxytext I/执行之前: 执行之前做点事情
08-11 17:47:30.364 31042-31042/com.chs.proxytext I/ShuiAn_price: 5000
08-11 17:47:30.364 31042-31042/com.chs.proxytext I/执行之后: 执行之后做点事情

     通过打印的log可以看到 ,当代理对象执行其方法的时候,会跳到handler中通过invoke来执行真实对象中的真实方法。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值