设计模式——代理模式

一 前言

代理模式(Proxy Pattern)也称为委托模式。那么代理模式是啥呢?其实代理在我们日常生活中也并不少见,对于程序员来说最常接触的莫过于代理上网了,连上代理服务器地址,就可以轻松畅游全世界的网络;还有每天吃饭时赶进度是常事,叫公司的同事帮忙买饭也是一种代理;如果你碰到辞职老板不给你发工资,那么你还得请个律师帮你打官司,这也是一种代理。总而言之,也许你并不留意,但是代理的确是无处不在,现实生活中如此,我们的Code世界里也是如此

二 定义

为其他对象提供一种代理以控制对这个对象的访问。

三 使用场景

当无法或不想直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口。

四 代码实例

4.1 静态代理

我们举个简单的例子,小民以前在公司上班时,就遇到过被老板拖欠工资甚至克扣工资的情况,这种情况下小民还是通过法律途径来解决问题,一旦小民选择了走法律途径解决该纠纷,那么不可避免地就需要请一个律师来作为自己的诉讼代理人,我们将诉讼的流程抽象在一个接口类中。

4.1.1 诉讼接口类

interface ILawsuit {


    // 提交申请
    fun submit()

    // 进行举证
    fun burden()

    // 开始辩护
    fun defend()
    
    // 诉讼完成
    fun finish()
}

4.1.2 具体诉讼人

class XiaoMin:ILawsuit {

    override fun submit() {
        // 老板欠小民工资 小民只好申请仲裁
        println("老板拖欠工资!特此申请仲裁!")
    }

    override fun burden() {
        // 小民证据充足,不怕告不赢
        println("这是合同书和过去一年的银行工资流水!")
    }

    override fun defend() {
        // 铁证如山,辩护也没什么好说的
        println("证据确凿!不需要再说什么了!")
    }

    override fun finish() {
        // 结果也是肯定的,必赢
        println("诉讼成功!判决老板即日起七天内结算工资")
    }

}

4.1.3 代理律师

如上所述,该类实现ILawsuit并对其中4个方法作出具体的实现逻辑,逻辑很简单,都只是输出一段话而已,当然,小民自己是不会去打官司的,于是小民请个律师代替自己进行诉讼。

class Lawyer:ILawsuit  {
    private var mLawsuit // 持有一个具体被代理者的引用
            : ILawsuit? = null

    fun Lawyer(lawsuit: ILawsuit?) {
        mLawsuit = lawsuit
    }

    override fun submit() {
        mLawsuit!!.submit()
    }

    override fun burden() {
        mLawsuit!!.burden()
    }

    override fun defend() {
        mLawsuit!!.defend()
    }

    override fun finish() {
        mLawsuit!!.finish()
    }

}

4.1.4 客户类中的调用执行过程

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // 构造一个小民……
    val xiaomin: ILawsuit = XiaoMin()
    // 构造一个代理律师并将小民作为构造参数传递进去
    val lawyer: ILawsuit = Lawyer(xiaomin)
    // 律师提交诉讼申请
    lawyer.submit()
    // 律师进行举证
    lawyer.burden()
    // 律师代替小民进行辩护
    lawyer.defend()
    // 完成诉讼
    lawyer.finish()
}

结果:
System.out: 老板拖欠工资!特此申请仲裁!
System.out: 这是合同书和过去一年的银行工资流水!
System.out: 证据确凿!不需要再说什么了!
System.out: 诉讼成功!判决老板即日起七天内结算工资



运行结果很简单这里不再给出,大家可以看到,其实代理模式也很简单,其主要还是一种委托机制,真实对象将方法的执行委托给代理对象,而且委托得干净利落毫不做作,这也是为什么代理模式也称为委托模式的原因,相信大家不难理解。除此之外,大家其实可以继续发散思维,其实我们的代理类完全可以代理多个被代理类,就像上面的例子一样,一个律师可以代理多个人打官司,这是没有任何问题的,而具体到底是代理的哪个人,这就要看代理类中所持有的实际对象类型。

4.2 动态代理

静态代理如上述示例那样,代理者的代码由程序员自己或通过一些自动化工具生成固定的代码再对其进行编译,也就是说在我们的代码运行前代理类的class编译文件就已存在;而动态代理则与静态代理相反,通过反射机制动态地生成代理者的对象,也就是说我们在code阶段压根就不需要知道代理谁,代理谁我们将会在执行阶段决定。而Java也给我们提供了一个便捷的动态代理接口InvocationHandler,实现该接口需要重写其调用方法invoke。

4.2.1 动态代理类

class DynamicProxy(var obj:Any?): InvocationHandler {

    override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
          return method?.invoke(obj)
    }
    
}

4.2.2 客户类中的调用执行过程

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    // 构造一个小民……
    val xiaomin: ILawsuit = XiaoMin()
    // 构造一个动态代理
    val proxy = DynamicProxy(xiaomin)
    // 获取被代理类小民的ClassLoader
    val loader = xiaomin.javaClass.classLoader
    // 动态构造一个代理者律师
    val lawyer =
        Proxy.newProxyInstance(loader, arrayOf(ILawsuit::class.java), proxy) as ILawsuit
    // 律师提交诉讼申请
    lawyer.submit()
    // 律师进行举证
    lawyer.burden()
    // 律师代替小民进行辩护
    lawyer.defend()
    // 完成诉讼
    lawyer.finish()
}

结果:
System.out: 老板拖欠工资!特此申请仲裁!
System.out: 这是合同书和过去一年的银行工资流水!
System.out: 证据确凿!不需要再说什么了!
System.out: 诉讼成功!判决老板即日起七天内结算工资

五 总结

代理模式应用广泛。我们讲到的其他形式的结构型模式中,你都可以看到代理模式的影子,有些模式单独作为一种设计模式,倒不如说是对代理模式的一种针对性优化。而且代理模式几乎没有什么缺点可言,它是细分化至很小的一种模式,要真的说一个缺点,那么就是所有设计模式的通病:对类的增加,不过在这种孰优孰劣的局势下,就算对类的稍微增加又何妨呢?

六 Android源码应用

1.android的binder机制(AMS,PMS,WMS等系统服务代理对象的获取)
2.AIDL

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值