代理模式的定义:
代理模式也称为委托模式;为其他对象提供一种代理以控制对这个对象的访问。
代理模式的使用场景:
当无法或不想直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口。
代理模式的UML类图:
角色介绍:
Subject:抽象主题类。该类的职责是声明真实主题与代理的共同接口方法,该类既可以是一个抽象类也可以是一个接口;
RealSubject:真实主题类。该类也被称为委托类或者代理类,该类定义了代理所表示的真实对象,尤其执行具体的业务逻辑方法,而客户类则通过代理类间接地调用真实主题类中定义的方法;
ProxySubjet:代理类。该类也被称为委托类或者代理类,该类持有一个对真实主题类的引用,在其所实现的接口方法中调用真实主题类中相应的接口方法执行,以此起到代理的作用。
Client:客户类,即使用代理类的类型。
代理模式简单实现(一):
//诉讼接口类(抽象主题类)
public interface ILawsuit {
//提交申请
void submit();
//进行举证
void burden();
//开始辩护
void defend();
//诉讼完成
void finish();
}
//具体诉讼人(真实主题类)
public class XiaoMin implements ILawsuit {
@Override
public void submit() {
//老板欠小民工资,小民只好申请仲裁
System.out.print("老板拖欠工资!特此申请仲裁!");
}
@Override
public void burden() {
//小民证据充足,不怕告不赢
System.out.print("这是合同书和过去一年的银行工资流水!");
}
@Override
public void defend() {
//证据确凿
System.out.print("证据确凿,无须再说!");
}
@Override
public void finish() {
//诉讼成功
System.out.print("诉讼成功!判决老板即日起七天内结算工资!");
}
}
//代理律师 (代理类)
public class Lawyer implements ILawsuit {
private ILawsuit mILawsuit;//持有一个具体被代理的对象
public Lawyer(ILawsuit iLawsuit) {
this.mILawsuit = iLawsuit;
}
@Override
public void submit() {
this.mILawsuit.submit();
}
@Override
public void burden() {
this.mILawsuit.burden();
}
@Override
public void defend() {
this.mILawsuit.defend();
}
@Override
public void finish() {
this.mILawsuit.finish();
}
}
public class Client {
public static void main(String[] args) {
//构造一个小明对象
ILawsuit xiaoming = new XiaoMin();
//构造一个代理律师并将小明对象作为参数传递进去
ILawsuit lawyer = new Lawyer(xiaoming);
//律师提交诉讼
lawyer.submit();
//律师进行举证
lawyer.burden();
//律师代替小明进行辩护
lawyer.defend();
//完成诉讼
lawyer.finish();
}
//我们的代理类完全可以代理多个被代理类,就像该例子一样,一个律师可以代理多个人打官司,这是没有问题的
//而具体到底是代理哪个人,这就要看代理类中持有的实际对象类型,上述例子中实际对象是小明,也就是代理的小明;
}
代理模式大致分为两大部分:一是静态代理,二是动态代理;
静态代理:代理者的代码有程序员自己或者通过一些自动化工具生成固定的代码再进行编译,也就是说我们的代码在运行前代理类class编译文件就已存在;
动态代理:与静态代理相反,通过反射机制动态生成代理者对象,也就是说我们在code阶段压根不需要知道代理谁,代理谁我们将在执行阶段决定。
而Java也给我们提供了一个便捷的动态代理接口InvocationHandler,实现该接口需要重写其调用方法invoke。我们主要通过invoke方法来调用具体的被代理方法,也就是真实的方法。
//动态代理
public class DynamicProxy implements InvocationHandler {
private Object object;//被代理的类引用
public DynamicProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//调用 被代理类对象 的方法
Object result = method.invoke(object, args);
return result;
}
//声明一个Object的引用,该引用将指向被代理类,而我们调用被代理类的具体方法则在invoke方法中执行。
//也就是说 我们原来由代理类所做的工作现在由InvocationHandler来处理,不再需要关心到底代理谁。
//修改客户端逻辑
}
public class Client {
public static void main(String[] args) {
//构造一个小明对象
ILawsuit xiaoming = new XiaoMin();
//构造一个动态代理
DynamicProxy proxy = new DynamicProxy(xiaoming);
//获取被代理类小民的ClassLoader
ClassLoader classLoader = xiaoming.getClass().getClassLoader();
//动态构造一个代理者律师
ILawsuit lawyer = (ILawsuit) Proxy.newProxyInstance(classLoader, new Class[]{ILawsuit.class}, proxy);
//律师提交诉讼
lawyer.submit();
//律师进行举证
lawyer.burden();
//律师代替小明进行辩护
lawyer.defend();
//完成诉讼
lawyer.finish();
}
//动态代理通过一个代理类来代理N多个被代理类,其本质是对代理者与被代理者进行解耦,是两者没有直接的耦合关系。
// 相对而言静态代理则只能为给定接口下的实现类做代理,如果接口不同那么就需要重新定义不同的代理类,比较复杂,
// 但是静态代理更符合面向对象原则。
}
备注:《设计模式》的学习笔记,仅为本人的学习记录,勿喷!!!