(七)设计模式-代理模式

1、定义

为其他对象提供一种代理以控制对这个对象的访问。

2、使用场景

快递小哥给小明打电话,让小明下去取快递,结果小明在开会没办法马上离开,只好让同事小王去帮他到楼下取一下快递,然后小王到了楼下找到快递小哥,然后快递小哥核对信息后把包裹转交给了小王,小王将包裹带回公司给了小明。小明非常感谢他。

3、代码结构UML图

在这里插入图片描述

4、类的实现

(1)、IPickUp(取快递接口 抽象)
public interface IPickUp {
    void pickBooks();
    void pickPhone();
    void pickFruit();
}
(2)、Proxy(代理人)
public class Proxy implements IPickUp{
    private Receiver receiver;

    public Proxy(Courier courier) {
        receiver=new Receiver(courier);
    }

    @Override
    public void pickBooks() {
        receiver.pickBooks();
    }

    @Override
    public void pickPhone() {
        receiver.pickPhone();
    }

    @Override
    public void pickFruit() {
        receiver.pickFruit();
    }
}
(3)、Receiver(收件人)
public class Receiver implements IPickUp {
    Courier courier;

    public Receiver(Courier courier) {
        this.courier = courier;
    }

    @Override
    public void pickBooks() {
        System.out.println(courier.getName() + " 我要取新买的书。");
    }

    @Override
    public void pickPhone() {
        System.out.println(courier.getName() + " 我要取新手机。");
    }

    @Override
    public void pickFruit() {
        System.out.println(courier.getName() + " 我要取一箱水果。");
    }
}
(4)、Courier(快递员)
public class Courier {

    private String name;

    public Courier(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

}

5、客户端调用

    public static void main(String[] args) {
        Courier xg = new Courier("快递小哥");
        Proxy proxy = new Proxy(xg);
        proxy.pickBooks();
        proxy.pickPhone();
        proxy.pickFruit();
    }

6、补充一个静态、动态代理的案例

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestProxy {

    public static void main(String[] args) {
        //静态代理类调用,不够灵活,每次需要写代理类
        //IObject iObject = new RealObject();
        //IObject proxyObject = new ProxyObject(iObject);
        //proxyObject.request();

        //动态代理类调用,十分灵活,可以不用写代理类,直接new InvocationHandler内部类,即可实现代理,jdk只支持代理接口,如果要代理类,只能使用反射替换类或其他方法
        IObject realObject = new RealObject();
        IObject proxy = (IObject) Proxy.newProxyInstance(IObject.class.getClassLoader(), new Class[]{IObject.class}, new ProxyObjectHandler(realObject));
        proxy.request();
    }


    /**
     * 代理接口
     */
    interface IObject {
        void request();
    }

    /**
     * 实际处理类
     */
    static class RealObject implements IObject {

        @Override
        public void request() {
            System.out.println("RealObject request==>");
        }
    }

    /**
     * 动态代理类,可直接使用内部类
	 * java.lang.reflect.InvocationHandler 是interface
	 * InvocationHandler是jdk自带的接口
	 * InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口,每一个proxy代理实例都有一个关联的调用处理程序;在代理实例调用方法时,方法调用被编码分派到调用处理程序的invoke方法。
	 * 与之相关Proxy 这个类很关键,每一个经过proxy代理的实例(proxy代理类,即通过Proxy.newProxyInstance创建的实例类),在调用其自身函数(方法)时,都会最终触发InvocationHandler的invoke函数(方法),
	 * 所以我们在实现InvocationHandler接口的invoke函数(方法)时,可以做一些自定义的事情。
     */
    static class ProxyObjectHandler implements InvocationHandler {
        IObject realObject;

        public ProxyObjectHandler(IObject realObject) {
            this.realObject = realObject;
        }

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

    /**
     * 静态代理类
     */
    static class ProxyObject implements IObject {

        IObject realObject;

        public ProxyObject(IObject iObject) {
            realObject = iObject;
        }

        @Override
        public void request() {
            realObject.request();
            System.out.println("ProxyObject request==>");
        }
    }
}

7、总结

代理模式使用场景一般分为几种:
第一、远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象的存在于不同地址空间的事实。webservice
第二、虚拟代理,是根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象。浏览器下载优化
第三、安全应用,用来控制真实对象访问时的权限。
第四、智能引用,是指当调用真实的对象时,代理处理另外一些事。计算对象的引用次数。
个人观点:代理就像是一个影子,攻击影子并不会伤害到真身。


参考:《大话设计模式》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值