设计模式--代理模式

代理模式

代理就是请别人帮你办事,但是别人只能在你委托的事情上代表你,不会拥有其他权限。代理更多是通过接口限定功能。

1. 使用场景

客户端不想直接访问某对象(保护代理),或直接访问某对象时有困难(远程代理),就可以使用一个代理对象来实现间接访问。真实对象和代理对象必须实现相同的接口,才能让客户端实现透明的访问。

2. 角色

  • Subject 抽象主题类,用于声明真实对象和代理对象共同的接口方法。
  • RealSubject 真实主题类,被代理的对象,客户端通过代理对象间接访问该对象中方法。
  • ProxySubject 代理类,持有真实对象的引用,并实现代理接口。

3. 实践

静态代理:只能给实现了约定的代理接口的类对象做代理。

// 例子1
// 抽象主题
public abstract class Subject {
    public abstract void visit();
}

// 真实类
public class RealSubject extends Subject {
    @Override
    public void visit() {
        System.out.println("真实对象: ");
    }
}

// 代理类,持有真实对象的引用,间接调用真实对象的方法
public class ProxySubject extends Subject {
    private RealSubject mSubject;
    public ProxySubject(RealSubject subject) {
        mSubject = subject;
    }
    @Override
    public void visit() {
        mSubject.visit();
    }
}

// 客户端调用
RealSubject real = new RealSubject()
ProxySubject proxy = new ProxySubject(real);
proxy.visit();

// 例子2
// 要代理的接口
public interface ILawsuit {
    // 提交申请
    void submit();
    // 进行举证
    void burden();
    // 开始辩护
    void defend();
    // 诉讼完成
    void finish();
}
// 被代理的类
public class XiaoMin implements ILawsuit {

    @Override
    public void submit() {
        System.out.println("老板拖欠工资,特此申请仲裁!");
    }

    @Override
    public void burden() {
        System.out.println("这是合同书和过去一年的银行流水!");
    }

    @Override
    public void defend() {
        System.out.println("证据确凿,不需要再说什么了!");
    }

    @Override
    public void finish() {
        System.out.println("诉讼胜利");
    }
}
// 代理类
public class Lawyer implements ILawsuit {
    private ILawsuit mILawsuit;

    public Lawyer(ILawsuit ILawsuit) {
        mILawsuit = ILawsuit;
    }

    @Override
    public void submit() {
        mILawsuit.submit();
    }

    @Override
    public void burden() {
        mILawsuit.burden();
    }

    @Override
    public void defend() {
        mILawsuit.defend();
    }

    @Override
    public void finish() {
        mILawsuit.finish();
    }
}
// 客户端调用
XiaoMin xiaomin = new XiaoMin();
ILawsuit lawyer = new Lawyer(xiaomin);
lawyer.submit();
lawyer.burden();
lawyer.defend();
lawyer.finish();

动态代理:通过反射动态生成代理者对象,在编码阶段代理类无需知道要代理哪些对象,即实现了代理类和被代理类的解耦。

// 创建动态代理类
public class DynamicProxy implements InvocationHandler {
    private Object mObject;

    public DynamicProxy(Object object) {
        mObject = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(mObject, args);
        return result;
    }
}

// 动态代理调用
System.out.println("**********动态代理**********");
DynamicProxy proxy1 = new DynamicProxy(xiaomin);
ClassLoader loader = xiaomin.getClass().getClassLoader();
ILawsuit lawsuit = (ILawsuit) Proxy.newProxyInstance(loader, new Class[]{ILawsuit.class}, proxy1);
lawsuit.submit();
lawsuit.burden();
lawsuit.defend();
lawsuit.finish();

JDK 中所使用的动态代理


public interface HelloWorld {
    String sayHello(String name);
}

public class HelloWorldImpl implements HelloWorld {
    @Override
    public String sayHello(String name) {
        System.out.println(name + "Hello!");
        return name;
    }
}

public class DynamicProxyJDK implements InvocationHandler {

    private Object target = null;

    /**
     * 建立原始对象和代理对象的绑定关系。
     *
     * @param target 原始对象
     * @return 代理对象
     */
    public Object bind(Object target) {
        this.target = target;
        // 创建被代理对象,需要指定类加载器,要代理的接口(原始对象有多个接口时,仅需要该代理对象实现的接口),代理对象(需要实现InvocationHandler接口,在invoke方法中实现代理逻辑)
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    /**
     * 在代理对象中调用被代理对象的指定方法。
     * 这个invoke是自动调用的。
     * @param proxy  代理对象,即bind方法生成的对象
     * @param method  所代理的方法
     * @param args 所代理方法所需的参数
     * @return 返回代理方法的返回值
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始代理方法");
        Object result = method.invoke(target, args);
        System.out.println("结束代理方法");
        return result;
    }

}


HelloWorld target=new HelloWorldImpl();

HelloWorld proxy = (HelloWorld) new DynamicProxyJDK().bind(target);

proxy.sayHello("kkkk");

4. 总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值