代理模式也称为委托模式,是一种结构型设计
模式;
定义:
为其他对象提供一种代理以控制对这个对象的访问;
使用场景:
当无法或不想直接访问某个对象
或访问某个对象存在困难时
,可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口;
Subject:
抽象主题类,该类的主要职责是申明真实主题与代理的共同接口方法,该类即可以是一个抽象类也可以是一个接口;RealSubject:
真实主题类,该类也称为被委托类或被代理类,该类定义了代理所表示的真实对象,由其执行具体的业务逻辑方法,而客户类则通过代理类间接地调用真实主题类中定义的方法;ProxySubject:
代理类,该类也称为委托类或代理类,该类持有一个对真实主题类的引用,在其所实现的接口方法中调用真实主题类中响应的接口方法执行,以此起到代理的作用;Client:
客户端类,使用代理类;定义:
代理类在编译阶段生成,在程序运行之前就已经存在的代理模式,称为静态代理;
这里我们以租客租房为例
,租客租房一般会找对应的租房中介,租房中介负责租房,同样,办理退房的时候也交给中介去处理即可;
IRental
/**
* 租房,抽象主题角色
*/
interface IRental {
/**
* 租房
*/
fun renting()
/**
* 退租
*/
fun rentingOut()
}
Tenant
/**
* 租客,真实主题类
*/
class Tenant(private val name: String) : IRental {
override fun renting() {
println("$name 办理租房手续")
}
override fun rentingOut() {
println("$name 办理退房手续")
}
}
RentalProxy
/**
* 租房中介,代理类
*/
class RentalProxy(private val rental: IRental) : IRental {
override fun renting() {
rental.renting()
}
override fun rentingOut() {
rental.rentingOut()
}
}
object Test {
@JvmStatic
fun main(args: Array<String>) {
//定义租客
val tenant = Tenant("Alice")
//租房中介
val rentalProxy = RentalProxy(tenant)
rentalProxy.renting()
println("------------------")
rentalProxy.rentingOut()
}
}
输出结果:
Alice 办理租房手续
------------------
Alice 办理退房手续
优点:
静态代理对客户端隐藏了被代理类接口的具体实现类,在一定程度上实现了解耦合,同时提高了安全性;
缺点:
由于静态代理所存在的问题,才有了动态代理
;
定义:
在程序运行期,创建目标对象的代理对象,对目标对象中的方法进行功能性增强的一种技术。
也就是说代理类是在程序运行时才产生的;
在java中使用Proxy类的newProxyInstance()方法去创建一个代理类的实例对象;
我们还是以租客租房为例,这里通过动态代理来实现;
IRental
/**
* 租房,抽象主题角色
*/
interface IRental {
/**
* 租房
*/
fun renting()
/**
* 退租
*/
fun rentingOut()
}
Tenant
/**
* 租客,真实主题类
*/
class Tenant(private val name: String) : IRental {
override fun renting() {
println("$name 办理租房手续")
}
override fun rentingOut() {
println("$name 办理退房手续")
}
}
InvocationHandler接口
,TenantInvocationHandler
class TenantInvocationHandler(private val tenant: IRental) : InvocationHandler {
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
return method?.invoke(tenant) //当调用被代理对象的方法时,都在统一到这里执行
}
}
object Test {
@JvmStatic
fun main(args: Array<String>) {
//定义租客
val tenant = Tenant("Alice")
//使用动态代理
val proxy = Proxy.newProxyInstance(
tenant::class.java.classLoader,
arrayOf(IRental::class.java),
TenantInvocationHandler(tenant)
) as IRental
proxy.renting()
println("----------------------")
proxy.rentingOut()
}
}
结果输出:
Alice 办理租房手续
----------------------
Alice 办理退房手续
优点:
如果小伙伴对动态代理的实现原理
感兴趣,可以移步:Android动态代理源码分析
Binder进程间通信原理
,通过AIDL
实现进程间通信,都会生成代理类,最终客户端通过代理类调用远程服务的方法;Retrofit的实现
,高明的动态代理模式使用,这里不再赘述,感兴趣的小伙伴可以参考:Retrofit原理解析代理模式基本没有什么缺点可言,尤其是动态代理,在Android开发中运用十分广泛,值得我们深入学习;
如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )