代理模式------读书笔记

意图

代理模式主要是为了控制对象的访问,意图只要有以下三种:
1、代理模式主要是为另一个对象提供代理,以控制对另一个对象的访问。
2、通过代理间接支持分布式、受控以及智能访问,
3、添加一个包装器或者委托以保护真正的组件不受过度复杂性的影响。

代理的种类

设计一个代理:当客户端第一次请求代理时,就实例化真实的对象,并将引发的请求转发给这个真实的对象。然后,所有之后的请求都直接转发到封装的真实对象。

主要有四种代理:
1、虚拟代理。当创建对象的代价非常高时,使用这种代理作为该对象的一个“替代品”。真实的对象只有在客户端第一次访问或者请求的时候创建(比如说图片加载)。
2、远程代理。此为远程对象的本地代表(在不同的地址空空间运行的远程对象)。本地代表是指可以由本地方法调用的对象,其行为会转发到远程对象中。比如说RPC中的stub,skeleton,就是提供了远程代理的功能。
3、保护代理。这种代理主要控制对敏感对象的访问。代理对象检查调用方是否具有各种所需的访问权限。
4、智能代理。主要用在访问对象时插入其他操作。

  • 计算实际对象的引用次数,当没有其他对象引用该对象时,自动释放该对象(智能指针)
  • 当第一次引用持久对象时,将其加载到内存中
  • 在访问真实对象之前检查它是否被锁定,以确保没有其他对象可以更改它。

远程代理

能够调用本地对象,然后将每个请求转发到远程对象上。此时,需要一些辅助对象,来协助我们做这些事情。这些辅助对象使客户就像在调用本地对象的方法一样。

客户调用客户辅助对象上的方法,方法客户辅助对象就是真正的服务。客户辅助对象再负责为我们转发这些请求。

在服务端,服务辅助对象从客户辅助对象中接受请求(通过socket连接),将调用的信息解包,然后调用真正服务对象上的真正方法。

服务辅助对象可以从服务中得到返回值,将它打包,然后运回客户辅助对象,客户辅助对象对信息解包,最后将返回值交给客户对象,

在这里插入图片描述

java RMI

RMI提供了客户辅助对象和服务辅助对象,为客户辅助对象创建和服务对象相同的方法。RMI的好处在于你不必晴子写任何网络或I/O代码。客户程序调用远程方法就和在运行在客户自己的本地JVM上对对象进行正常方法调用一样。
RMI将客户辅助对象称为stub(桩),把服务辅助对象称为skeleton(骨架)。

类图

在这里插入图片描述

java动态代理

类图

在这里插入图片描述

我们使用java的动态代理来实现保护代理。因为java已经为你创建了proxy类,所以你需要有什么办法来告诉Proxy类你要做什么。我们不能像以前一样把代码放到proxy中,因为proxy不是我们直接实现的,我们把它放到InvocationHandle中,这个类的工作是相应代理的任何调用,你可以把InvocationHandler想成是代理收到方法调用后,请求做实际工作的对象。

我们为什么要使用动态代理呢?比如说我们实现一个打分系统,该系统有个人年龄性别等信息,也有别人给自己的评分信息。,我们自己不可以改变自己的HotOrNot评分,也不可以改变其他人的个人信息,因此,我们需要创建两个代理,一个访问你自己的PersonBean对象,另一个访问另一人的PersonBean对象。这样代理就可以控制在每一种情况下允许哪一种请求。
创建这种代理,必须使用java中的动态代理。

代码

个人信息接口类

 interface PersonBean{
        fun getName() : String?
        fun getGender() : String?
        fun getInterests() : String?
        fun getHotOrNotRating() : Int?
    
        fun setName(name: String)
        fun setGender(gender : String)
        fun setInterests(interest : String)
        fun setHotOrNotRating(hotRating : Int)
    
    }

个人信息实现类

class PersonBeanImpl : PersonBean{
    var nameStr : String? = null
    var genderStr : String? = null
    var interestStr : String? = null
    var hotRatingInt : Int? = 0
    var ratingCount = 0

    override fun getName(): String? {
        return nameStr
    }

    override fun getGender(): String? {
        return genderStr
    }

    override fun getInterests(): String? {
        return interestStr
    }

    override fun getHotOrNotRating(): Int? {
        if (ratingCount == 0){
            return 0
        }
        return hotRatingInt?.div(ratingCount)
    }

    override fun setName(name: String) {
        nameStr = name
    }

    override fun setGender(gender: String) {
        genderStr = gender
    }

    override fun setInterests(interest: String) {
        interestStr = interest
    }

    override fun setHotOrNotRating(hotRating: Int) {
        hotRatingInt?.plus(hotRating)
        ratingCount++
    }

}

真正实现控制访问的handler

自己的信息

  import java.lang.reflect.InvocationHandler
    import java.lang.reflect.Method
    
    /**
     * 自己只能修改年龄性别等信息,而不能修改自己的评分等信息。
     */
    
    class OwnerInvocationHandler(val personBean: PersonBeanImpl) : InvocationHandler{
        override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
            if (method!!.name.startsWith("get")){
                return method.invoke(personBean, args!![0])
            }else if (method.name == "setHotOrNotRating"){
                throw IllegalAccessException()
            }else if (method.name.startsWith("set")){
                method.invoke(personBean, args!![0])
            }
            return "null"
        }
    
    }

别人的信息

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

/**
 * 别人只能更改其他的评分,而不能修改别人的性别年龄等信息
 */
class NonOwnerInvocationHandler (val personBean: PersonBeanImpl): InvocationHandler{
    override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any {
        if (method!!.name.startsWith("get")){
            throw IllegalAccessException()
        }else if (method.name == "setHotOrNotRating"){
            return method.invoke(personBean, args!![0])
        }else if (method.name.startsWith("set")){
            throw IllegalAccessException()
        }
        return "null"
    }

}

测试类

import java.lang.reflect.Proxy

fun main(args : Array<String>){
    val person  = PersonBeanImpl()
    val personProxy  = Proxy.newProxyInstance(person.javaClass.classLoader,person.javaClass.interfaces, OwnerInvocationHandler(person)) as PersonBean
    personProxy.setGender("3")
    print(personProxy)
}

猜你喜欢

转载自blog.csdn.net/u011337574/article/details/88542833