(《设计模式解析与实战——何红辉,关爱民》读书笔记)
一、定义
为其他对象提供一种代理以控制对这个对象的访问。
比如,代理上网。
二、使用场景
当无法或不想直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口。
三、代理模式的通用模式代码
package com.proxy.pattern;
/**
* 抽象主题类:主要职责是声明真实主题与代理的共同接口方法
*/
public abstract class Subject {
/**
* 一个普通的业务方法
*/
public abstract void visit();
}
package com.proxy.pattern;
/**
* 实现抽象主题的真实主题类:被代理类,定义了代理所表示的真实对象,由其执行具体的业务逻辑方法
*/
public class RealSubject extends Subject{
@Override
public void visit() {
System.out.println("RealSubject中visit的具体逻辑!");
}
}
package com.proxy.pattern;
/**
* 代理类:该类持有一个对真实主题类的引用调用真实主题类中响应的接口方法执行,以此起到代理的作用
*/
public class ProxySubject extends Subject{
// 持有真实主题的引用
private RealSubject mRealSubject;
public ProxySubject(RealSubject mRealSubject) {
this.mRealSubject = mRealSubject;
}
@Override
public void visit() {
// 通过真实主题引用的对象调用真实主题中的逻辑方法
mRealSubject.visit();
}
}
package com.proxy.pattern;
/**
* 客户类:使用代理类的类型
*/
public class Client {
public static void main(String[] args) {
// 构造一个真实主题对象
RealSubject realSubject = new RealSubject();
// 通过真实主题对象构造一个代理对象
ProxySubject proxySubject = new ProxySubject(realSubject);
// 调用代理的相关方法
proxySubject.visit();
}
}
运行结果:
以上是静态代理,而代理类不只可以代理一个对象,这时就需要使用动态代理:
/**
* 抽象主题类:主要职责是声明真实主题与代理的共同接口方法
*/
public interface Subject {
/**
* 一个普通的业务方法
*/
public void visit();
}
修改为接口
相应的类改为implements:
最后修改客户类:
/**
* 客户类:使用代理类的类型
*/
public class Client {
public static void main(String[] args) {
// 构造一个真实主题对象
RealSubject realSubject = new RealSubject();
// 构造一个动态代理
DynamicProxy dynamicProxy = new DynamicProxy(realSubject);
// 获取被代理类的ClassLoader
ClassLoader classLoader = realSubject.getClass().getClassLoader();
// 动态构造一个代理类
Subject proxySubject = (Subject) Proxy.newProxyInstance(
classLoader, new Class[]{Subject.class}, dynamicProxy);
// // 通过真实主题对象构造一个代理对象
// ProxySubject proxySubject = new ProxySubject(realSubject);
// 调用代理的相关方法
proxySubject.visit();
}
}
运行结果和之前一样。
静态代理和动态代理是从代码方面来区分的。从适用范围来区分分为下面四类:
(1)远程代理(Remote Proxy):为某个对象在不同的内存地址空间提供局部代理。使系统可以将Server部分的实现隐藏,以便Client可以不必考虑Server的存在;
(2)虚拟代理(Virtual Proxy):使用一个代理对象表示一个十分耗资源的对象并在真正需要时才创建;
(3)保护代理(Protection Proxy):使用代理控制对原始对象的访问。该类型的代理常被用于原始对象有不同访问权限的情况;
(4)智能引用(Smart Reference):在访问原始对象时执行一些自己的附加操作并对指向原始对象的引用计数。
静态和动态代理都可以应用于上述4种情形,两者是各自独立的变化。
四、总结
代理模式应用广泛,几乎没有什么缺点,要说缺点,那就是所有设计模式的通病——类的膨胀。