【设计模式】代理模式

374 阅读3分钟

前言

代理模式(Proxy Pattern)是一种常用的结构型设计模式,它通过为其他对象提供一种代理以控制对这个对象的访问。在本文中,我们将深入探讨代理模式的组成、类图、使用场景以及在 Android 中的具体应用。

代理模式是一种非常常见的设计模式,它可以为其他对象提供一种代理以控制对这个对象的访问。代理模式通过在代理对象和实际对象之间添加一层中介层,使得代理对象能够在不改变原有代码的情况下,对访问进行控制和管理。

组成

代理模式由以下几个组成部分:

  • 抽象对象接口(Subject):定义了代理对象和实际对象之间共同实现的方法。

  • 实际对象类(RealSubject):实现了抽象对象接口定义的方法。

  • 代理对象类(Proxy):实现了抽象对象接口定义的方法,并维护一个对实际对象的引用。

类图

下图是代理模式的类图:

image.png

(图源 | 图说设计模式)

使用场景

代理模式通常用于以下几种情况:

  • 远程代理:为了隐藏对象存在于不同地址空间的事实,可以使用远程代理。远程代理可以将网络通信的细节隐藏在代理对象后面,使得客户端无需知道实际对象是否存在于远程地址空间中。

  • 虚拟代理:为了在创建实际对象时节省资源,可以使用虚拟代理。虚拟代理可以在需要的时候创建实际对象,并将其存储在代理对象中。在实际对象被访问前,代理对象会先检查是否需要创建实际对象。

  • 安全代理:为了控制访问对象的权限,可以使用安全代理。安全代理会对客户端的访问进行权限控制,只有符合条件的客户端才能访问实际对象。

Android 中涉及到的代理模式

在 Android 中,代理模式有很多应用场景。以下是一些常见的代理模式的应用场景:

  • Binder 机制:在 Android 中,进程间通信(IPC)主要通过 Binder 机制实现。Binder 机制就是一种代理模式,客户端会将调用信息发送给 Binder 代理对象,代理对象再将调用信息转发给实际对象。Binder 代理对象会维护一个指向 Binder 服务端的引用,通过这个引用,Binder 代理对象可以将调用信息发送到服务端。

  • 动态代理:在 Android 中,还经常使用动态代理来实现一些常见的功能,如事件监听器、注解等。动态代理可以在运行时生成代理对象,通过代理对象来代替实际对象的操作。

下面是一个使用动态代理的示例:

public class MainActivity extends AppCompatActivity {
    private Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mButton = findViewById(R.id.button);
        mButton.setOnClickListener((View.OnClickListener) Proxy.newProxyInstance(
                View.OnClickListener.class.getClassLoader(),
                new Class<?>[]{View.OnClickListener.class},
                new OnClickListenerProxy(mButton)
        ));
    }
}

class OnClickListenerProxy implements InvocationHandler {
    private Object target;

    OnClickListenerProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if ("onClick".equals(method.getName())) {
            Log.d("OnClickListenerProxy", "before onClick");
            Object result = method.invoke(target, args);
            Log.d("OnClickListenerProxy", "after onClick");
            return result;
        }
        return null;
    }
}

以上代码中,使用了动态代理来实现 Button 的点击事件监听。OnClickListenerProxy 实现了 InvocationHandler 接口,并在其中通过反射来调用 Button 的 onClick() 方法,从而在执行该方法之前和之后,分别打印了一条日志。

总结

代理模式是一种非常实用的设计模式,它通过为其他对象提供一种代理来控制对这个对象的访问,可以有效地解耦和简化代码。在 Android 中,代理模式有很多应用场景,如 Binder 机制、动态代理等。对于 Android 开发者来说,熟练掌握代理模式的原理和实现,可以更好地应对日常开发工作中的问题,提高开发效率。