代理模式简记

以NFC举例,代码不具备实操功能
接口:INFCService.java

    boolean isSupportNFC();
    boolean isOpen();

    void openNFC(Context context);

    void closeNFC(Context context);
    //通信交流
    void communication();

}

具体实现类:NfcDao.java

public class NfcDao implements INFCService {
    private static volatile NfcDao instance;
    private static NfcAdapter nfcAdapter;

    public NfcDao(Context context) {
        nfcAdapter = NfcAdapter.getDefaultAdapter(context);
    }

    public static NfcDao getInstance(Context context) {
        // 双重检查锁定模式 Proxy.newProxyInstance()
        if (instance == null) {
            synchronized (NfcDao.class) {
                if (instance == null) {
                    instance = new NfcDao(context);
                }
            }
        }
        return instance;
    }

    @Override
    public boolean isSupportNFC() {
        if (nfcAdapter != null) {
            return true;
        }
        return false;
    }

    @Override
    public boolean isOpen() {
        if (nfcAdapter != null){
            return nfcAdapter.isEnabled();
        }
        return false;
    }

    @Override
    public void openNFC(Context context) {
        if (nfcAdapter != null && !nfcAdapter.isEnabled()) {
            // 创建一个意图以打开 NFC 设置屏幕
            Intent intent = new Intent(Settings.ACTION_NFC_SETTINGS);
            // 启动活动以打开 NFC 设置屏幕
            context.startActivity(intent);
        }
    }

    @Override
    public void closeNFC(Context context) {
        // 关闭 NFC
        try {
            Settings.Global.putInt(context.getContentResolver(), Settings.Global.RADIO_NFC, 0);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 请求关闭 NFC 的系统设置
        Intent intent = new Intent(Settings.ACTION_NFC_SETTINGS);
        context.startActivity(intent);
    }

    @Override
    public void communication() {

    }
}
  • 静态代理
public class NFCProxy implements INFCService {
    private INFCService iNfcService;

    public NFCProxy(INFCService iNfcService) {
        this.iNfcService = iNfcService;
    }

    @Override
    public boolean isSupportNFC() {
        return iNfcService.isSupportNFC();
    }

    @Override
    public boolean isOpen() {
        return iNfcService.isOpen();
    }

    @Override
    public void openNFC(Context context) {
        iNfcService.openNFC(context);
    }

    @Override
    public void closeNFC(Context context) {
        iNfcService.closeNFC(context);
    }

    @Override
    public void communication() {
        iNfcService.communication();
    }
}
  • 动态代理
public class NFCDynamicProxy<T> {
    private T target;
    public NFCDynamicProxy(T target) {
        this.target = target;
    }
      //只能用于无参构造
    public NFCDynamicProxy(Class<T> target) {
        try {
            this.target = target.newInstance();
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        }
    }

    /*实验性代码,反射中的有参构造不要android中使用
    /,其参数类型无法精准获取抽象类只能获取其实现类类型
    ,在传入Context后其类型可能是Application或Activity
结果:失败,Type没发强制转换,构造参数类型没发动态获取,此处仅作保留*/
    public NFCDynamicProxy(Class<T> target, Object... params) {
        Constructor<?>[] constructors = target.getConstructors();
      //target.getConstructor(new Class[tClass])
        try {
            Class<?>[] clzTypeParams = new Class[params.length];
            for (int i = 0; i < params.length; i++) {
                clzTypeParams[i] = params[i].getClass();
                //实验性代码
                Type type = params[i].getClass().getGenericSuperclass();
                Class<T> tClass = (Class<T>) type;
                LogUtil.d("超类名:"+tClass.getName());
            }
            Constructor<T> constructor = target.getDeclaredConstructor(clzTypeParams);
            this.target = constructor.newInstance(params);
        }catch (Exception e){
            LogUtil.e(e.getMessage());
        }
    }

    public T getProxyInstance() {
        T iNfc = (T) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),   //ClassLoader 类加载器
                target.getClass().getInterfaces(),    //代理对象接口(必须是接口)
                new NfcClientInvocationHandler<T>(target));
        return iNfc;
    }
}

NfcClientInvocationHandler.java

public class NfcClientInvocationHandler<T> implements InvocationHandler {
    private T t;
    public NfcClientInvocationHandler(T t) {
        this.t = t;
    }

    //被代理的对象
    @Override
    public T invoke(Object proxy, Method method, Object[] args) throws Throwable {
        LogUtil.i("代理执行方法:" + method.getName() + "=>");
        if (args != null && BuildConfig.DEBUG) {
            for (int i = 0; i < args.length; i++) {
                LogUtil.i("参数为:" + args.toString());
            }
        }

        if (method.getDeclaringClass() == t.getClass()) {
            return (T) method.invoke(this, args);
        }else {
            return (T) method.invoke(t, args);
        }
    }
}

代理模式好处:给对象套一层壳,便于AOP操作;将操作与调用分离,可以在执行过程中灵活的切换操作对象而不需要改调用者

  • 优点
    灵活性: 使用代理模式可以轻松地在运行时添加或修改目标对象的行为。
    解耦: 代理模式可以降低目标对象和客户端之间的耦合度。
    代码复用: 可以在不修改目标对象的情况下,为其添加额外的功能。
  • 缺点
    性能开销: 由于所有的方法调用都需要通过代理对象进行,可能会导致一定的性能开销。
    复杂性: 使用代理模式可能会增加代码的复杂性,特别是当涉及到多个代理时
  • 场景,添加日志记录、事务管理,给模块之前的调用进行解耦
动态代理与静态代理的优劣:
  • 静态代理:
    类的代码在运行前就已经存在,在动态代理中,代理对象是在运行时动态生成的。Java 的 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口提供了这种能力的基础。
    优点
    性能稍微好一些,因为没有运行时的动态类加载和代理对象创建。
    代码更简单,易于理解和维护。
    缺点
    不够灵活,如果需要为多个类添加相似的功能,会导致代码重复。
    违反了开放/封闭原则,每次需要修改目标对象的行为时,都需要修改代理类的代码。
  • 动态代理
    在动态代理中,代理对象是在运行时动态生成的。Java 的 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口提供了这种能力的基础。
    优点
    高度灵活,可以动态地为任何目标对象添加或修改功能。
    更符合开放/封闭原则,可以在不修改目标对象代码的情况下,通过添加新的代理处理器来修改目标对象的行为。
    缺点
    性能可能稍差,因为所有的方法调用都需要通过代理对象进行,这增加了一层间接性。
    代码可能更复杂,需要更多的理解和维护
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容